Compare commits

...
19 Commits
Author SHA1 Message Date
Mamadou Babaei 1db86d9778 bump the plugin version to v2.0.7 2024-05-29 12:47:33 +02:00
Mamadou Babaei 0de86b508a make the allbreaker assets compatible with ue 5.1+ again 2024-05-29 12:46:51 +02:00
Mamadou Babaei 65a96a462b bump the plugin version to v2.0.6 2024-05-29 11:40:07 +02:00
Mamadou Babaei 6b7c28c379 bump the plugin version to v2.0.5 2024-05-22 17:32:43 +02:00
Mamadou Babaei af0be8c1f7 fix the wrong palm bone names on the allbreaker virtual hand models 2024-05-22 17:31:58 +02:00
Mamadou Babaei 49a12f64a4 bump the plugin version to v2.0.4 2024-05-17 11:39:57 +02:00
Mamadou Babaei 76d03b1fe8 bump the plugin version to v2.0.3 2024-05-16 20:00:18 +02:00
Mamadou Babaei d8ae5923d5 fix v2.0.2 UE 5.4 RunUAT build issues that mostly caused by missing headers 2024-05-15 04:34:46 +02:00
Mamadou Babaei befb07470e improve target platform detection when building SenseGloveConnectImpl and SenseGloveCoreImpl modules and also distinguish x64 builds from arm64 on windows 2024-05-15 04:34:38 +02:00
Mamadou Babaei b467c679de fix: asking CppCompileEnvironment for a single Architecture, but it has multiple Architectures (arm64, x64) 2024-05-15 04:34:30 +02:00
Mamadou Babaei 9afbd8e54f bump the plugin version to v2.0.2 2024-04-25 12:56:05 +02:00
Mamadou Babaei 4e0d01c3de bump the plugin version to v2.0.1 2024-04-15 15:03:17 +02:00
Mamadou Babaei 8681f78c22 do not call FSGHandLayer::ResetCalibration on every backend initialization 2024-04-15 14:52:20 +02:00
Mamadou Babaei 84e8f46d35 only instantiate the connected glove once instead of recreating and destroying it every frame 2024-04-15 14:52:14 +02:00
Mamadou Babaei 3f0dd4a5b9 bump senseglove libraries to v2.102.0-35d4de3f 2024-04-15 14:52:05 +02:00
Mamadou Babaei d0970504ce fix the wrong header file description sections for the header files 2024-04-15 14:51:58 +02:00
Mamadou Babaei 0c73eccc16 update the changelog with the unreleased changes 2024-04-15 14:51:52 +02:00
Mamadou Babaei f3b9155955 update the outdated platform support matrix remarks 2024-03-23 17:23:03 +01:00
Mamadou Babaei 45da7baa95 add ue 5.4 to the list of supported engines through azure devops 2024-03-23 16:57:47 +01:00
91 changed files with 380 additions and 409 deletions
+77
View File
@@ -5,6 +5,83 @@ 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.0.7] - 2024-05-29
This is a bugfix release with no actual plugin code changes, only fixing issues with binary assets incompatible with UE versions earlier than 5.4.
### Fixed
- Make the Allbreaker assets compatible with UE5.1+ again as the v2.0.5 update breaks compatibility with UE versions earlier than 5.4, thus leaving the engine unable to load those assets.
## [2.0.6] - 2024-05-29
This is a bugfix release with no actual plugin code changes, only removing development/test assets from UE 5.3 that were never meant to be shipped.
### Removed
- Removed the dev/test virtual hand models that leaked into the 5.3 branch.
### Fixed
## [2.0.5] - 2024-05-22
This is a bugfix release with no actual plugin code changes, only focusing on fixing the Allbreaker virtual hand model issues.
### Fixed
- Fix the wrong palm bone names on the Allbreaker virtual hand models.
## [2.0.4] - 2024-05-17
This is a bugfix release with no actual plugin's code change.
### Fixed
- Fix our in-house Unreal Engine Marketplace submission tool's configurations where the Content folder (containing the Allbreaker hand model) is mistakenly ignored during the submission. This release reintroduces the Virtual Hand Model and its material missing from the previous release.
- Fix the SenseGlove.uproject's wrong versioning submitted to the Unreal Engine Marketplace.
## [2.0.3] - 2024-05-15
This is a bugfix release addressing mostly RunUAT build issues on Unreal Engine 5.4.
### Fixed
- Fix UE 5.4 RunUAT build issue: "Asking CppCompileEnvironment for a single Architecture, but it has multiple Architectures (arm64, x64)", affecting SenseGloveConnectImpl and SenseGloveCoreImpl modues.
- Improved target platform detection when building SenseGloveConnectImpl and SenseGloveCoreImpl modules and also distinguishing the x64 builds from arm64 on Microsoft Windows.
- Fix other UE 5.4 RunUAT build issues, mostly caused by missing headers.
### Removed
- Removed support for Android armeabi-v7a and x86 architectures as they are no longer supported by the supported engine versions.
## [2.0.2] - 2024-04-25
This is a patch release with no code changes.
### Added
- Introduce official Unreal Engine 5.4 support to the Unreal Engine Marketplace.
### Changed
- Updated the Platform Support Matrix with the latest changes. This is the last release to support Unreal Engine 5.1 as we no longer are able to push updates for this release to the Unreal Engine Marketplace. The v2.0.1 release for Unreal Engine 5.1 can be obtained from the Unreal Engine Marketplace, and v2.0.2 through our Microsoft Azure DevOps repositories. Please note that there are no actual code changes between these two releases and in terms of functionality they are almost identical.
## [2.0.1] - 2024-04-15
This is a bugfix release.
### Fixed
- Fix a bug inside both SGVirtualHandComponent and SGWristTrackerComponent where the connected glove's UObject instance gets destroyed and re-instantiated every frame. With this fix now the glove instance will be created or destroyed only when a glove connects to or disconnects from the system.
- Update the outdated Platform Support Matrix and its remarks section to reflect the latest status information.
- Fix the wrong header file description sections for the header files inside <code>SenseGloveKismet/Public/SGKismet/</code>.
### Changed
- SenseGlove libraries have been updated to v2.102.0-35d4de3f.
- Together, SenseGlove libraries v2.102.0-35d4de3f and SenseCom v1.6.1 remove the need to call ResetCalibration every time and are able to store and load calibration profiles from disk.
- SesenGloveBackend module is no longer calling FSGHandLayer::ResetCalibration on every backend initialization.
## [2.0.0] - 2024-03-22 ## [2.0.0] - 2024-03-22
This is the second major release of the SenseGlove Unreal Engine Plugin adding support for Nova 2 with enormous breaking changes to the current C++ and Blueprint APIs. This is the second major release of the SenseGlove Unreal Engine Plugin adding support for Nova 2 with enormous breaking changes to the current C++ and Blueprint APIs.
+14 -24
View File
@@ -8,10 +8,10 @@ This repository relies on Git LFS for storing binary blobs (e.g. third-party lib
| | **Windows (MSVC 2017)** | **Windows (MSVC 2019)** | **Windows (MSVC 2022)** | **Linux x86-64 (Native Toolchain)** | **Linux AArch64 (Native Toolchain)** | **Android (NDK)** | **UE Marketplace Version** | **Azure DevOps Version** | | | **Windows (MSVC 2017)** | **Windows (MSVC 2019)** | **Windows (MSVC 2022)** | **Linux x86-64 (Native Toolchain)** | **Linux AArch64 (Native Toolchain)** | **Android (NDK)** | **UE Marketplace Version** | **Azure DevOps Version** |
|----------|:-----------------------:|:-----------------------:|:-----------------------:|:-----------------------------------:|:------------------------------------:|:-----------------:|:--------------------------:|:------------------------:| |----------|:-----------------------:|:-----------------------:|:-----------------------:|:-----------------------------------:|:------------------------------------:|:-----------------:|:--------------------------:|:------------------------:|
| **5.4** | ❌ | ❌ | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x (r25b) | | | | **5.4** | ❌ | ❌ | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x (r25b) | ✅ v2.0.7 | ✅ v2.0.7 |
| **5.3** | ❌ | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x (r25b) | ✅ v2.0.0 | ✅ v2.0.0 | | **5.3** | ❌ | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x (r25b) | ✅ v2.0.7 | ✅ v2.0.7 |
| **5.2** | ❌ | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x (r25b) | ✅ v2.0.0 | ✅ v2.0.0 | | **5.2** | ❌ | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x | ✅ v2.0.x (r25b) | ✅ v2.0.7 | ✅ v2.0.7 |
| **5.1** | ❌ | v2.0.x | v2.0.x | v2.0.x | v2.0.x | v2.0.x (r25b) | v2.0.0 | v2.0.0 | | **5.1** | ❌ | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x (r25b) | ⚠️ v2.0.1 | ⚠️ 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 |
| **4.27** | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x (r21e) | ⚠️ v1.3.1 | ⚠️ v1.4.3 | | **4.27** | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x | ⚠️ v1.4.x (r21e) | ⚠️ v1.3.1 | ⚠️ v1.4.3 |
| **4.26** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ | ❌ | ⚠️ v1.0.4 | | **4.26** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ | ❌ | ⚠️ v1.0.4 |
@@ -27,11 +27,9 @@ This repository relies on Git LFS for storing binary blobs (e.g. third-party lib
Remarks: Remarks:
* Per [Epic's Marketplace Guidelines](https://www.unrealengine.com/en-US/marketplace-guidelines) in regards to Code Plugins (sections 2.6.3.d and 3.1.b), we are only able to distribute or update the SenseGlove plugin for the last 3 stable versions of Unreal Engine. As a result, we won't be able to publish updates or bug fixes for the older versions of the Engine except on rare occasions and only through our official repository on Microsoft Azure DevOps. * Per [Epic's Marketplace Guidelines](https://www.unrealengine.com/en-US/marketplace-guidelines) in regards to Code Plugins (sections 2.6.3.d and 3.1.b), we are only able to distribute or update the SenseGlove plugin for the last 3 stable versions of Unreal Engine. As a result, we won't be able to publish updates or bug fixes for the older versions of the Engine except on rare occasions and only through our official repository on Microsoft Azure DevOps.
* Microsoft Visual Studio 2022 is not supported by Unreal Engine 4.22 through 4.26.
* All third-party libraries on Windows built against Windows SDK 10.0. * All third-party libraries on Windows built against Windows SDK 10.0.
* Oculus support is only provided through the recommended Android NDK versions by Epic Games. * Oculus and VIVE support is only provided through the recommended Android NDK versions by Epic Games.
* The Unreal Engine 4.27+ support is provided for Android/Oculus development. * [wjwwood/serial](https://github.com/wjwwood/serial) requires Android NDK API Level 28+ in order to be built successfully.
* [wjwwood/serial](https://github.com/wjwwood/serial) requires Android NDK API Level 28+ in order to be built successfully, thus some older NDKs such as r14b.
* All third-party libraries target Android NDK API Level 29, thus any project relying on the plug-in should be build with the same NDK API Level. * All third-party libraries target Android NDK API Level 29, thus any project relying on the plug-in should be build with the same NDK API Level.
## Changelog ## Changelog
@@ -56,7 +54,7 @@ Please note that modules postfixed with **Impl** are intended for interal use an
## Planned Features Completion Status ## Planned Features Completion Status
### Implemented as of v2.0.0 ### Implemented as of v2.0.7
- [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.
@@ -86,7 +84,11 @@ Please note that modules postfixed with **Impl** are intended for interal use an
### Upcoming features planned for the v2.1.0 release ### Upcoming features planned for the v2.1.0 release
- [ ] Hand tracking compatible with OpenXR (or other generic hand tracking format). - [ ] OpenXR-compatible hand tracking (XR_EXT_hand_tracking) support.
- [ ] FXRMotionControllerData compatible hand animation system.
- [ ] FXRMotionControllerData compatible wrist tracking system.
- [ ] FXRMotionControllerData compatible hand interaction manipulation system.
- [ ] Ability to fallback to hand tracking when a glove is not present and use the bare hands for interactions, or a combination of glove and hand tracking if no motion controller input is detected.
### Planned features long-term ### Planned features long-term
@@ -179,19 +181,7 @@ Please note that modules postfixed with **Impl** are intended for interal use an
│ │ │ │ │ │
│ │ └── release │ │ └── release
│ │ │ │
── armv7 (32-bit ARM variant of Android) ── x64 (64-bit x86-64 variant of Android)
│ │ │
│ │ ├── debug
│ │ │
│ │ └── release
│ │
│ ├── x64 (64-bit x86-64 variant of Android)
│ │ │
│ │ ├── debug
│ │ │
│ │ └── release
│ │
│ └── x86 (32-bit x86 variant of Android)
│ │ │ │
│ ├── debug │ ├── debug
│ │ │ │
@@ -264,4 +254,4 @@ The SenseGlove plug-in for Unreal Engine is licensed under the terms of the [MIT
### Third-Party Licenses ### Third-Party Licenses
Please note that while the SenseGlove plug-in for Unreal Engine is made available under the [MIT License](LICENSE.md), it utilizes a few third-party libraries with permissive free licenses as well, in order to power various components. For a list of these libraries and their own respective open-source licenses take a look at [LICENSE-THIRD-PARTY.md](LICENSE-THIRD-PARTY.md), please. Please note that while the SenseGlove plug-in for Unreal Engine is made available under the [MIT License](LICENSE.md), it utilizes a few third-party libraries with permissive free licenses as well, in order to power various components. For a list of these libraries and their own respective open-source licenses take a look at [LICENSE-THIRD-PARTY.md](LICENSE-THIRD-PARTY.md), please.
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"Version": 1, "Version": 1,
"VersionName": "2.0.0", "VersionName": "2.0.7",
"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,8 @@
#include "SenseGlove/Components/SGGrabComponent.h" #include "SenseGlove/Components/SGGrabComponent.h"
#include "GameFramework/Actor.h"
struct USGGrabComponent::FImpl struct USGGrabComponent::FImpl
{ {
/************************ /************************
@@ -35,6 +35,8 @@
#include "SenseGlove/Components/SGTouchComponent.h" #include "SenseGlove/Components/SGTouchComponent.h"
#include "GameFramework/Actor.h"
struct USGTouchComponent::FImpl struct USGTouchComponent::FImpl
{ {
/************************ /************************
@@ -598,13 +598,18 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
} }
} }
const bool bGloveWasPresent = IsValid(Owner->Glove); bool bGloveConnected;
const bool bFoundGlove = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove); if (!IsValid(Owner->Glove) || !Owner->Glove->IsConnected())
if (!bFoundGlove && bGloveWasPresent)
{ {
SGLOG_ERROR(FString::Printf(TEXT("Could not find a %s glove!"), bGloveConnected = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
(Owner->IsRight() ? TEXT("right-handed") : TEXT("left-handed")))); if (!bGloveConnected)
{
Owner->Glove = nullptr;
}
}
else
{
bGloveConnected = true;
} }
const bool bIsEditor = IsEditor(); const bool bIsEditor = IsEditor();
@@ -613,7 +618,7 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
const bool bIsVisible = Owner->IsVisible(); const bool bIsVisible = Owner->IsVisible();
if (Owner->bHiddenInGameIfNoGloveDetected) if (Owner->bHiddenInGameIfNoGloveDetected)
{ {
if (bFoundGlove) if (bGloveConnected)
{ {
if (!bIsVisible) if (!bIsVisible)
{ {
@@ -637,7 +642,7 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
} }
} }
return bFoundGlove; return bGloveConnected;
} }
void USGVirtualHandComponent::FImpl::DrawDebugVirtualHand() const void USGVirtualHandComponent::FImpl::DrawDebugVirtualHand() const
@@ -250,21 +250,22 @@ bool USGWristTrackerComponent::FImpl::CheckGlove() const
} }
} }
const bool bGloveWasPresent = IsValid(Owner->Glove); bool bGloveConnected;
const bool bFoundGlove = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove); if (!IsValid(Owner->Glove) || !Owner->Glove->IsConnected())
if (!bFoundGlove && bGloveWasPresent)
{ {
SGLOG_ERROR(FString::Printf(TEXT("Could not find a %s glove!"), bGloveConnected = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
(Owner->IsRight() ? TEXT("right-handed") : TEXT("left-handed")))); if (!bGloveConnected)
{
Owner->Glove = nullptr;
}
} }
else
if (bFoundGlove)
{ {
bGloveConnected = true;
UpdateWristTrackingData(); UpdateWristTrackingData();
} }
return bFoundGlove; return bGloveConnected;
} }
void USGWristTrackerComponent::FImpl::UpdateMotionSource() const void USGWristTrackerComponent::FImpl::UpdateMotionSource() const
@@ -50,6 +50,8 @@
#include "SGInterop/SGIC_JNIEnv_Ptr.h" #include "SGInterop/SGIC_JNIEnv_Ptr.h"
#endif /* PLATFORM_ANDROID */ #endif /* PLATFORM_ANDROID */
#include "SGLog/SGLog.h"
int32 FSGConnectJNI::Initialize() int32 FSGConnectJNI::Initialize()
{ {
int32 Result = -999999; int32 Result = -999999;
@@ -118,10 +118,6 @@ bool USGBackend::InitializeBackend()
FSGDeviceList::Dispose(); FSGDeviceList::Dispose();
FSGDeviceList::Reinitialize(); FSGDeviceList::Reinitialize();
// Force reset the hands calibration.
FSGHandLayer::ResetCalibration(false);
FSGHandLayer::ResetCalibration(true);
bBackendInitialized = true; bBackendInitialized = true;
return true; return true;
@@ -37,6 +37,8 @@
#include <string> #include <string>
#include "Containers/StringConv.h"
#include "SGBuildHacks/SGInclude_Connect_SGConnect.h" #include "SGBuildHacks/SGInclude_Connect_SGConnect.h"
int32 FSGConnectImpl::Init() int32 FSGConnectImpl::Init()
@@ -35,6 +35,7 @@
#include "SGConnectImpl/SGExportedFunctions.h" #include "SGConnectImpl/SGExportedFunctions.h"
#include "Containers/StringConv.h"
#include "Templates/UnrealTemplate.h" #include "Templates/UnrealTemplate.h"
#if PLATFORM_ANDROID #if PLATFORM_ANDROID
@@ -81,70 +81,28 @@ public class SenseGloveConnectImpl : ModuleRules
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source")); string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty")); string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib")); string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "sgconnect"; string LibraryName = "sgconnect";
if (Target.Platform == UnrealTargetPlatform.Android) 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, "android"));
#if UE_5_1_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#elif UE_5_0_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r21e"));
#else
Debug.Assert(false, "Developing for Android on UE versions older than 5.0 is not supported!");
#endif
#if UE_5_2_OR_LATER LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
if (Target.Architecture == UnrealArch.Arm64) LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
}
else if (Target.Architecture == UnrealArch.X64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
}
else
{
Debug.Assert(false, "Unsupported Android architecture!");
}
#else
IAndroidToolChain ToolChain = AndroidExports.CreateToolChain(Target.ProjectFile);
List<string> Architectures = ToolChain.GetAllArchitectures();
foreach (string Arch in Architectures)
{
if (Arch == "-arm64")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
break;
}
else if (Arch == "-armv7")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "armv7"));
break;
}
else if (Arch == "-x64")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
break;
}
else if (Arch == "-86")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86"));
break;
}
else
{
Debug.Assert(false, "Unsupported Android architecture!");
break;
}
}
#endif
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
} }
else if (Target.Platform == UnrealTargetPlatform.Linux) else if (bIsLinux)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
@@ -161,11 +119,7 @@ public class SenseGloveConnectImpl : ModuleRules
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
} }
#if UE_5_0_OR_LATER else if (bIsLinuxArm64)
else if (Target.Platform == UnrealTargetPlatform.LinuxArm64)
#else
else if (Target.Platform == UnrealTargetPlatform.LinuxAArch64)
#endif
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
@@ -182,7 +136,7 @@ public class SenseGloveConnectImpl : ModuleRules
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
} }
else if (Target.Platform == UnrealTargetPlatform.Win64) else if (bIsWin64)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
switch (Target.WindowsPlatform.Compiler) switch (Target.WindowsPlatform.Compiler)
@@ -209,21 +163,42 @@ public class SenseGloveConnectImpl : ModuleRules
Debug.Assert(false, "Unsupported platform!"); Debug.Assert(false, "Unsupported platform!");
} }
bool bDebug = (Target.Configuration == UnrealTargetConfiguration.Debug); string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
if (bDebug) PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug")); 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 else
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release")); 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);
} }
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
PublicAdditionalLibraries.Add(LibraryPath);
} }
private void AddSerialLibrary(ReadOnlyTargetRules Target) private void AddSerialLibrary(ReadOnlyTargetRules Target)
@@ -232,70 +207,28 @@ public class SenseGloveConnectImpl : ModuleRules
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source")); string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty")); string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib")); string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "serial"; string LibraryName = "serial";
if (Target.Platform == UnrealTargetPlatform.Android) 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, "android"));
#if UE_5_1_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#elif UE_4_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r21e"));
#else
Debug.Assert(false, "Developing for Android on UE versions older than 5.0 is not supported!");
#endif
#if UE_5_2_OR_LATER LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
if (Target.Architecture == UnrealArch.Arm64) LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
}
else if (Target.Architecture == UnrealArch.X64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
}
else
{
Debug.Assert(false, "Unsupported Android architecture!");
}
#else
IAndroidToolChain ToolChain = AndroidExports.CreateToolChain(Target.ProjectFile);
List<string> Architectures = ToolChain.GetAllArchitectures();
foreach (string Arch in Architectures)
{
if (Arch == "-arm64")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
break;
}
else if (Arch == "-armv7")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "armv7"));
break;
}
else if (Arch == "-x64")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
break;
}
else if (Arch == "-86")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86"));
break;
}
else
{
Debug.Assert(false, "Unsupported Android architecture!");
break;
}
}
#endif
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
} }
else if (Target.Platform == UnrealTargetPlatform.Linux) else if (bIsLinux)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
@@ -312,11 +245,7 @@ public class SenseGloveConnectImpl : ModuleRules
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
} }
#if UE_5_0_OR_LATER else if (bIsLinuxArm64)
else if (Target.Platform == UnrealTargetPlatform.LinuxArm64)
#else
else if (Target.Platform == UnrealTargetPlatform.LinuxAArch64)
#endif
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
@@ -333,7 +262,7 @@ public class SenseGloveConnectImpl : ModuleRules
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
} }
else if (Target.Platform == UnrealTargetPlatform.Win64) else if (bIsWin64)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
switch (Target.WindowsPlatform.Compiler) switch (Target.WindowsPlatform.Compiler)
@@ -360,20 +289,41 @@ public class SenseGloveConnectImpl : ModuleRules
Debug.Assert(false, "Unsupported platform!"); Debug.Assert(false, "Unsupported platform!");
} }
bool bDebug = (Target.Configuration == UnrealTargetConfiguration.Debug); string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
if (bDebug) PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug")); 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 else
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release")); 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);
} }
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
PublicAdditionalLibraries.Add(LibraryPath);
} }
} }
@@ -35,6 +35,8 @@
#include "SGCore/SGDeviceList.h" #include "SGCore/SGDeviceList.h"
#include "Templates/SubclassOf.h"
#include "SGCore/SGBetaDevice.h" #include "SGCore/SGBetaDevice.h"
#include "SGCore/SGDevice.h" #include "SGCore/SGDevice.h"
#include "SGCore/SGDeviceImplCast.h" #include "SGCore/SGDeviceImplCast.h"
@@ -80,70 +80,28 @@ public class SenseGloveCoreImpl : ModuleRules
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source")); string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty")); string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib")); string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "sgcore"; string LibraryName = "sgcore";
if (Target.Platform == UnrealTargetPlatform.Android) 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, "android"));
#if UE_5_1_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#elif UE_5_0_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r21e"));
#else
Debug.Assert(false, "Developing for Android on UE versions older than 5.0 is not supported!");
#endif
#if UE_5_2_OR_LATER LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
if (Target.Architecture == UnrealArch.Arm64) LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
}
else if (Target.Architecture == UnrealArch.X64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
}
else
{
Debug.Assert(false, "Unsupported Android architecture!");
}
#else
IAndroidToolChain ToolChain = AndroidExports.CreateToolChain(Target.ProjectFile);
List<string> Architectures = ToolChain.GetAllArchitectures();
foreach (string Arch in Architectures)
{
if (Arch == "-arm64")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
break;
}
else if (Arch == "-armv7")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "armv7"));
break;
}
else if (Arch == "-x64")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
break;
}
else if (Arch == "-86")
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86"));
break;
}
else
{
Debug.Assert(false, "Unsupported Android architecture!");
break;
}
}
#endif
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
} }
else if (Target.Platform == UnrealTargetPlatform.Linux) else if (bIsLinux)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
@@ -160,11 +118,7 @@ public class SenseGloveCoreImpl : ModuleRules
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
} }
#if UE_5_0_OR_LATER else if (bIsLinuxArm64)
else if (Target.Platform == UnrealTargetPlatform.LinuxArm64)
#else
else if (Target.Platform == UnrealTargetPlatform.LinuxAArch64)
#endif
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName); LibraryName = string.Format("lib{0}.a", LibraryName);
@@ -181,7 +135,7 @@ public class SenseGloveCoreImpl : ModuleRules
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
} }
else if (Target.Platform == UnrealTargetPlatform.Win64) else if (bIsWin64)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64")); LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
switch (Target.WindowsPlatform.Compiler) switch (Target.WindowsPlatform.Compiler)
@@ -200,6 +154,7 @@ public class SenseGloveCoreImpl : ModuleRules
Debug.Assert(false, "Unsupported engine version or compiler!"); Debug.Assert(false, "Unsupported engine version or compiler!");
break; break;
} }
LibraryName = string.Format("{0}.lib", LibraryName); LibraryName = string.Format("{0}.lib", LibraryName);
} }
else else
@@ -207,20 +162,41 @@ public class SenseGloveCoreImpl : ModuleRules
Debug.Assert(false, "Unsupported platform!"); Debug.Assert(false, "Unsupported platform!");
} }
bool bDebug = (Target.Configuration == UnrealTargetConfiguration.Debug); string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
if (bDebug) PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug")); 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 else
{ {
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release")); 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);
} }
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
PublicAdditionalLibraries.Add(LibraryPath);
} }
} }
@@ -35,6 +35,8 @@
#pragma once #pragma once
#include "HAL/Platform.h"
#if PLATFORM_ANDROID #if PLATFORM_ANDROID
#include "Android/AndroidJavaEnv.h" #include "Android/AndroidJavaEnv.h"
@@ -35,6 +35,8 @@
#pragma once #pragma once
#include "HAL/Platform.h"
#if PLATFORM_ANDROID #if PLATFORM_ANDROID
#include "Android/AndroidJavaEnv.h" #include "Android/AndroidJavaEnv.h"
@@ -35,6 +35,8 @@
#pragma once #pragma once
#include "HAL/Platform.h"
#if PLATFORM_ANDROID #if PLATFORM_ANDROID
#include "Android/AndroidJavaEnv.h" #include "Android/AndroidJavaEnv.h"
@@ -29,9 +29,7 @@
* *
* @section DESCRIPTION * @section DESCRIPTION
* *
* A data class containing the minimum required data for a hand's forward *
* kinematics.
* Used in both kinematics and calibration.
*/ */
@@ -29,9 +29,7 @@
* *
* @section DESCRIPTION * @section DESCRIPTION
* *
* A data class containing the minimum required data for a hand's forward *
* kinematics.
* Used in both kinematics and calibration.
*/ */
@@ -29,9 +29,7 @@
* *
* @section DESCRIPTION * @section DESCRIPTION
* *
* A data class containing the minimum required data for a hand's forward *
* kinematics.
* Used in both kinematics and calibration.
*/ */
@@ -29,9 +29,7 @@
* *
* @section DESCRIPTION * @section DESCRIPTION
* *
* A data class containing the minimum required data for a hand's forward *
* kinematics.
* Used in both kinematics and calibration.
*/ */
@@ -29,9 +29,7 @@
* *
* @section DESCRIPTION * @section DESCRIPTION
* *
* A data class containing the minimum required data for a hand's forward *
* kinematics.
* Used in both kinematics and calibration.
*/ */
@@ -29,9 +29,7 @@
* *
* @section DESCRIPTION * @section DESCRIPTION
* *
* A data class containing the minimum required data for a hand's forward *
* kinematics.
* Used in both kinematics and calibration.
*/ */
@@ -37,6 +37,7 @@
#include "ISettingsModule.h" #include "ISettingsModule.h"
#include "ISettingsSection.h" #include "ISettingsSection.h"
#include "Modules/ModuleManager.h"
#include "SGLog/SGLog.h" #include "SGLog/SGLog.h"
#include "SGSettings/SGSettings.h" #include "SGSettings/SGSettings.h"
@@ -41,6 +41,9 @@
#include "SGAngles.h" #include "SGAngles.h"
#include "Containers/Array.h" #include "Containers/Array.h"
#include "Containers/StringConv.h" #include "Containers/StringConv.h"
#include "Math/Quat.h"
#include "Math/Rotator.h"
#include "Math/Vector.h"
#include "Templates/UnrealTemplate.h" #include "Templates/UnrealTemplate.h"
#include "SGUtils/SGUnits.h" #include "SGUtils/SGUnits.h"
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.
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.
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.
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.