Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c56af0e1f
|
||
|
|
9cbdf5cea7
|
||
|
|
032422de1c
|
||
|
|
0f89d1c4dd
|
||
|
|
8d289c0f2f
|
||
|
|
62a2dd44f0
|
||
|
|
c3001c588c
|
||
|
|
f3b21fecfa
|
||
|
|
94e1b9ffcb
|
||
|
|
01078b6cd6
|
||
|
|
a62f615036
|
||
|
|
5213282f25
|
||
|
|
58712b48ad
|
||
|
|
1684a40c20
|
||
|
|
cbcb6abaee
|
||
|
|
1ff21f70c7
|
||
|
|
3020fcdd7a
|
||
|
|
d3467ac7f2
|
||
|
|
4a212edbca
|
||
|
|
5ebcb583f6
|
||
|
|
9b99399641
|
||
|
|
691fd43cd1
|
||
|
|
716ce49ca7
|
||
|
|
f4a368a61c
|
||
|
|
22c97d2d77
|
||
|
|
e89643f8d0
|
||
|
|
24eb573007
|
||
|
|
3b29f54622
|
||
|
|
61e4aa2e6a
|
||
|
|
0dccac6432
|
||
|
|
12bfcfe80d
|
||
|
|
407d4ea14c
|
||
|
|
1dff735623
|
||
|
|
1834ea5d5c
|
||
|
|
29d2aad490
|
||
|
|
82f354e340
|
||
|
|
d4b06e062e
|
||
|
|
4a005a85b0
|
||
|
|
919e7f17dd
|
||
|
|
31cb7ee20b
|
||
|
|
ae268ebde7
|
||
|
|
220ddf28a6
|
||
|
|
091b0ade32
|
||
|
|
b0c32ccad4
|
||
|
|
838b5fe557
|
||
|
|
78735026c2
|
||
|
|
e1ced44a69
|
||
|
|
f92e870c56
|
||
|
|
a4941d4d7d
|
||
|
|
4a72839ece
|
||
|
|
1a89f202c5
|
||
|
|
f1b14c7673
|
||
|
|
a35e706283
|
||
|
|
708fce2f0c
|
||
|
|
9116e4a234
|
||
|
|
9ee7e3f0df
|
||
|
|
4a03aedb3c
|
||
|
|
1eadfd249b
|
||
|
|
d2a1583217
|
||
|
|
786c7d8380
|
||
|
|
53a70569bd
|
||
|
|
4f01d61640
|
||
|
|
a0bd230c73
|
||
|
|
81eb3bb90c
|
||
|
|
8253ec277d
|
||
|
|
9598c772fc
|
||
|
|
01eed66701
|
||
|
|
9ae0b1ea2f
|
||
|
|
a6baab575c
|
||
|
|
79c31ecf50
|
||
|
|
d80697ee72
|
||
|
|
50f76c7a0d
|
||
|
|
846dac5a88
|
||
|
|
c314920d89
|
||
|
|
55405672f8
|
||
|
|
f2656f1bea
|
||
|
|
eead79b8f5
|
||
|
|
5ae86cbf66
|
||
|
|
5902aafff0
|
||
|
|
4e591d6290
|
||
|
|
46f885fa5a
|
||
|
|
51190d6ead
|
||
|
|
96fb9c3c8e
|
||
|
|
9bde1878ed
|
||
|
|
7c271d30ce
|
||
|
|
d61183a960
|
||
|
|
caa0bf259a
|
||
|
|
e9a6fc3df0
|
||
|
|
bdfb75920b
|
||
|
|
2e5ba17d89
|
||
|
|
25dca3f8f3
|
||
|
|
b4cdbec91a
|
||
|
|
58ca6a5bca
|
||
|
|
f29c428b16
|
||
|
|
759c94bcbf
|
||
|
|
4393af7317
|
||
|
|
a31b14d48c
|
||
|
|
854ce6a198
|
||
|
|
e0e743b63d
|
||
|
|
e32453dfef
|
||
|
|
d57d3ffa4a
|
||
|
|
8194072025
|
||
|
|
cf7fba949d
|
||
|
|
0dd745bbe6
|
||
|
|
0ca24adee3
|
||
|
|
b947685598
|
||
|
|
11534229f4
|
||
|
|
77d7b4eb23
|
||
|
|
25e8fd2d07
|
||
|
|
dafc7c0ad6
|
||
|
|
2b818dd11b
|
||
|
|
cf115e2782
|
||
|
|
f709be4935
|
||
|
|
a0f3b84aab
|
||
|
|
de83672ef1
|
||
|
|
a465321f9d
|
||
|
|
392fcd4932
|
||
|
|
8a1e9ff300
|
||
|
|
fd257711c2
|
||
|
|
ff59e7f712
|
||
|
|
06b27847cb
|
||
|
|
94301a321c
|
||
|
|
0ea98272a9
|
||
|
|
14a43e0630
|
||
|
|
a7f4a83850
|
||
|
|
9101d2061a
|
||
|
|
3e025f3e47
|
||
|
|
2ba5c0f2fc
|
||
|
|
66e60ff18a
|
||
|
|
25f8ef6393
|
||
|
|
e30ca2c9ed
|
||
|
|
adcfa63415
|
||
|
|
02cb09d504
|
||
|
|
89a9200413
|
||
|
|
e50a65ca92
|
||
|
|
955bb69cf9
|
||
|
|
3335ee2ec3
|
||
|
|
b0113a908e
|
||
|
|
50971e6051
|
||
|
|
78bb5adff6
|
||
|
|
95fb454576
|
||
|
|
c0d4a50f76
|
||
|
|
092f4a1327
|
||
|
|
5bbb51b0fe
|
||
|
|
6006a22c06
|
||
|
|
ffdb3657d6
|
||
|
|
f5b93b45ed
|
||
|
|
08e8eec206
|
||
|
|
b47de02afe
|
||
|
|
e58522bfd1
|
||
|
|
a3827277b1
|
||
|
|
5c6f9ad18b
|
||
|
|
f3845ef65f
|
||
|
|
1c7b1891f7
|
||
|
|
54bda06bdc
|
||
|
|
f9dbc1f11e
|
||
|
|
16df85607d
|
||
|
|
7ec9e80c3a
|
||
|
|
0f514a2f95
|
||
|
|
14ebc3327b
|
||
|
|
3b6a2341fa
|
||
|
|
fb5babc0f1
|
||
|
|
4db4bf397a
|
||
|
|
6ef49c204c
|
||
|
|
2785c1ae38
|
||
|
|
756abf819d
|
||
|
|
7bfb6c1517
|
||
|
|
f916999716
|
||
|
|
672209ab03
|
||
|
|
e215d7192f
|
||
|
|
9ea20a2bc8
|
||
|
|
fae227db6c
|
||
|
|
4d18afb9d6
|
||
|
|
f9bc33f2fd
|
||
|
|
ae46cb6240
|
||
|
|
225f2d3d30
|
||
|
|
acd955f815
|
||
|
|
a07f54dea8
|
||
|
|
729e10681b
|
||
|
|
3289fadcde
|
||
|
|
d958ae6382
|
||
|
|
c8ca169f3b
|
||
|
|
c391c0a794
|
||
|
|
4a3ca10802
|
||
|
|
5bf4e8264f
|
||
|
|
cb388efd30
|
||
|
|
2d2b43d4ad
|
||
|
|
bb3452ce7c
|
||
|
|
fbcf503351
|
||
|
|
88832fd6bd
|
||
|
|
f25259c556
|
||
|
|
ce1a342b28
|
||
|
|
18b0ea9eea
|
||
|
|
49bd844c1c
|
||
|
|
8c15c54077
|
||
|
|
2312b75c85
|
||
|
|
696d77f629
|
||
|
|
3ffbd72def
|
||
|
|
29e3458cd1
|
||
|
|
344027b781
|
||
|
|
8e86d9f656
|
||
|
|
37b30cd099
|
||
|
|
45b1c36cf7
|
||
|
|
340503b61d
|
||
|
|
6b076bb5fb
|
||
|
|
f5050ac081
|
||
|
|
1ab4410c21
|
||
|
|
b683aa22af
|
||
|
|
aac0bb8a05
|
||
|
|
4903e11dee
|
||
|
|
b3b0639e72
|
||
|
|
ae43aead8c
|
||
|
|
4f08fe0286
|
||
|
|
4b28a863f0
|
||
|
|
ed0cfe18c3
|
||
|
|
85e4ddaac5
|
+1
-1
@@ -124,4 +124,4 @@ DerivedDataCache/*
|
||||
.ignore
|
||||
|
||||
# Do not ignore anything inside the ThirdParty directory at all
|
||||
!ThirdParty/**/*
|
||||
!Source/ThirdParty/**/*
|
||||
|
||||
+130
-1
@@ -1,7 +1,136 @@
|
||||
# Changelog
|
||||
|
||||
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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
## [v1.2.1] - 2023-03-30
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix RunUAT build issues with Android.
|
||||
|
||||
## [v1.2.0] - 2023-03-28
|
||||
|
||||
This release breaks ABI/API compatibility with the previous versions.
|
||||
|
||||
### Added
|
||||
|
||||
- Android / Oculus on-device glove calibration.
|
||||
- Introduced the animated Virtual Hand Model (as a set of virtual hand and wrist tracker components and an actor) with in-editor animation availability.
|
||||
- Introduced SGPawn, SGPlayerController, SGGameModeBase, etc classes.
|
||||
- Added an internal SenseGloveCoreTypes module in order to share common SenseGloveCore types between various modules.
|
||||
- Segregated Android binaries for NDK r21e (UE 4.27 and 5.0) and r25b (UE 5.1, 5.2).
|
||||
- Fully functional and stable Linux development support.
|
||||
- Fully functional and stable Unreal Engine 5.2 preview support has been added.
|
||||
- Added a Plugin's settings manager and two new modules SenseGloveSettings and SenseGloveSettingsKismet.
|
||||
|
||||
### Changed
|
||||
|
||||
- SenseGlove libraries have been updated to the Linux-aware version: v2.5.0-8069342.
|
||||
- API has changed to use degrees instead of radians.
|
||||
- SGCoordinates utility class name has been changed to SGAngles and now the plugin API uses degrees in contrast of SenseGlove libraries by default.
|
||||
- Migrate common nested array types into the SenseGloveTypes module from the SenseGloveCore module.
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed a few thousands lines of archaic pre-public-release dead code.
|
||||
- Dropped Android NDK r21b binaries used by the older engine versions.
|
||||
- Purged the dead code for dropped engine versions by v1.1.1 (4.22, 4.23, 4.24, 4.25, and 4.26) that carried over to the current version.
|
||||
- Removed redundant SGConnectImpl/SGPlatform.
|
||||
- Removed redundant SGTypes/SGConnectTypes.
|
||||
|
||||
### Known Issues
|
||||
|
||||
- Wrist Tracker's offsets are a bit off (e.g. on Quest 2), scheduled to be fixed in the next patch release.
|
||||
|
||||
## [1.1.1] - 2023-02-07
|
||||
|
||||
### Added
|
||||
|
||||
- Initial support for the upcoming Unreal Engine 5.2.
|
||||
- Add support for Android armeabi-v7a with neon, x86-64, and x86 builds in addition to arm64-v8a.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix various Android build issues.
|
||||
- Some minor fixes and improvements.
|
||||
|
||||
### Changed
|
||||
|
||||
- Bump SenseGlove libraries to v2.1.2-95ec6e7.
|
||||
|
||||
## [1.1.0] - 2023-02-03
|
||||
|
||||
### Added
|
||||
|
||||
- Whitelist Android as a target platform.
|
||||
- Introduce Android support.
|
||||
- Add third-pary library SGConnect for Android v1.1.0.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix Android build issues caused by the log module.
|
||||
|
||||
### Changed
|
||||
|
||||
- SGConnect and SGCore libraries have been updated to v2.1.1-0569c74.
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed the enum utils class due to ANY_PACKAGE deprecation warnings in Unreal Engine 5.1.
|
||||
- Support for older versions of the Engine (namely, 4.22, 4.23, 4.24, 4.25, and 4.26) has been dropped.
|
||||
|
||||
## [1.0.4] - 2022-12-02
|
||||
|
||||
This is a minor release focusing mostly on adherence to the Unreal Engine Marketplace Guidelines based on the feedback from Epic Games.
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for MSVC 2017
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated SenseGlove libraries (SGCore/SGConnect) to v2.0.4.
|
||||
|
||||
## [1.0.3] - 2022-11-29
|
||||
|
||||
This is a minor release focusing on adherence to the Unreal Engine Marketplace Guidelines based on the feedback from Epic Games.
|
||||
|
||||
### Changed
|
||||
|
||||
- Adjust Config/FilterPlugin.ini in order to conform to Epic's Market Place Guidelines.
|
||||
|
||||
## [1.0.2] - 2022-11-27
|
||||
|
||||
This is a minor release focusing on adherence to the Unreal Engine Marketplace Guidelines based on the feedback from Epic Games.
|
||||
|
||||
### Added
|
||||
|
||||
- Added the newly acquired Unreal Engine Market Place Offer ID to the .uplugin file.
|
||||
- List the dot files inside FilterPlugin.ini file as well.
|
||||
- Add the copyright notice to the source files missing it.
|
||||
- Add the SenseGlove SDK license to the third-party license file.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix the readme typos and errors.
|
||||
- Minor fixes in the changelog for previous releases.
|
||||
|
||||
## [1.0.1] - 2022-11-25
|
||||
|
||||
### Changed
|
||||
|
||||
- Exposed SenseGloveTypes as a public dependency in SenseGloveConnect and SenseGloveCore modules, so that the C++ users of the API don't need to explicitly add it as a dependency.
|
||||
- Cleaned up the redundant headers/modules dependencies from SGCore headers.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix RunUAT build issues prior to Epic Store submission.
|
||||
|
||||
## [1.0.0] - 2022-11-24
|
||||
|
||||
### Added
|
||||
|
||||
- Initial public release of the SenseGlove haptic API for Unreal Engine with support for Microsoft Windows and GNU/Linux.
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
[FilterPlugin]
|
||||
/CHANGELOG.md
|
||||
/Config/FilterPlugin.ini
|
||||
/LICENSE.md
|
||||
/LICENSE-THIRD-PARTY.md
|
||||
/README.md
|
||||
|
||||
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.
+47
-3
@@ -2,6 +2,39 @@
|
||||
|
||||
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.
|
||||
|
||||
### SenseGlove SDK
|
||||
|
||||
```
|
||||
SENSEGLOVE SDK LICENSE
|
||||
|
||||
Purchase of the Product does not entitle you to ownership or a license to any
|
||||
software generated by SenseGlove for use with the Product (the “Software”).
|
||||
To the extent that SenseGlove, in its sole discretion, grants you access to any
|
||||
such Software, the Software is licensed by us or by the relevant licensor/owner
|
||||
subject to the relevant end-user license agreement or other license terms
|
||||
included with the Product and/or on the SenseGlove Websites including the Github
|
||||
page of SenseGlove (the “License Terms“).
|
||||
|
||||
Specifically, SenseGlove shall have sole discretion to determine and change the
|
||||
availability, nature, features, content, versioning of any Software that it
|
||||
makes available to you, for download through the the Github page of SenseGlove
|
||||
or otherwise (including the SenseGlove software developer kit (“SDK”)).
|
||||
Purchase of a Product does not entitle you to access to any specific features,
|
||||
content or version of the SDK, including and especially versions of the SDK that
|
||||
have not yet been made available to the public. SenseGlove will have no
|
||||
obligation to provide any updates or upgrades to any Software it makes available
|
||||
to you, but in the event that it does, such updates, upgrades and any
|
||||
documentation will be subject to the License Terms available at
|
||||
https://www.senseglove.com/solutions/.
|
||||
|
||||
Except to the extent expressly provided by us in writing or under the License
|
||||
Terms, the Software is provided “AS IS” without any warranties, terms or
|
||||
conditions as to quality, fitness for purpose, non-infringement, performance or
|
||||
correspondence with description and we do not offer any warranties or guarantees
|
||||
in relation to the Software installation, configuration or error/defect
|
||||
correction.
|
||||
```
|
||||
|
||||
## Boost C++ Libraries License
|
||||
|
||||
```
|
||||
@@ -35,9 +68,20 @@ DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
Copyright (c) 2012 William Woodall, John Harrison
|
||||
|
||||
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:
|
||||
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 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.
|
||||
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.
|
||||
```
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ The SenseGlove plug-in for Unreal Engine is licensed under the terms of the MIT
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 - 2022 SenseGlove
|
||||
Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -1,44 +1,43 @@
|
||||
# The SenseGlove Unreal Engine Plugin
|
||||
|
||||
## ⚠️ DISCLAIMER: Experimental Release
|
||||
|
||||
This is an initial experimental release for public evaluation and may not be considered *production ready*, yet. This repository is under active development and there might be known or unknown bugs lurking around. Use it at your own risk.
|
||||
|
||||
## How to Download
|
||||
|
||||
This repository relies on Git LFS for storing binary blobs (e.g. third-party libraries). Sadly, there is a known issue with Microsoft Azure public LFS repositories that requires credential for LFS checkouts on https (LFS ssh checkouts are not supported at all). Unless, you are part of SenseGlove organization on Microsoft Azure there is no easy way to fully clone this repository using Git. Thus, the best way to download this repository is to use the 'kebab' (three vertical dots) menu next to the clone button, in order to download the whole repository including LFS objects as a unified zip file.
|
||||
|
||||
## Platform Support Matrix
|
||||
|
||||
| | **Windows<br>(MSVC 2019)** | **Windows<br>(MSVC 2022)** | **Linux<br>(Native Toolchain)** | **macOS** | **Oculus Mobile<br>(Android NDK r21b)** |
|
||||
|----------|:--------------------------:|:--------------------------:|:-------------------------------:|:---------:|:---------------------------------------:|
|
||||
| **4.22** | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
| **4.23** | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
| **4.24** | ✅ | ❌ | ✅ | ❌ | ❌ |
|
||||
| **4.25** | ✅ | ❌ | ✅ | ❌ | ❓ |
|
||||
| **4.26** | ✅ | ❌ | ✅ | ❌ | ❓ |
|
||||
| **4.27** | ✅ | ✅ | ✅ | ❌ | ❓ |
|
||||
| **5.0** | ✅ | ✅ | ✅ | ❌ | ❓ |
|
||||
| **5.1** | ✅ | ✅ | ✅ | ❌ | ❓ |
|
||||
| | **Windows (MSVC 2017)** | **Windows (MSVC 2019)** | **Windows (MSVC 2022)** | **Linux (Native Toolchain)** | **macOS** | **Oculus Mobile (Android NDK)** |
|
||||
|:--------:|:-----------------------:|:-----------------------:|:-----------------------:|:----------------------------:|:---------:|:-------------------------------:|
|
||||
| **4.22** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ |
|
||||
| **4.23** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ |
|
||||
| **4.24** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ |
|
||||
| **4.25** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ |
|
||||
| **4.26** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ |
|
||||
| **4.27** | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ❌ | ✅ v1.2.x (r21e) |
|
||||
| **5.0** | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ❌ | ✅ v1.2.x (r21e) |
|
||||
| **5.1** | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ❌ | ✅ v1.2.x (r25b) |
|
||||
| **5.2** | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ✅ v1.2.x | ❌ | ✅ v1.2.x (r25b) |
|
||||
|
||||
* <code>✅</code> Supported
|
||||
* <code>❌</code> Not Supported
|
||||
* <code>❓</code> Unknown or Untested
|
||||
* <code>⚠️</code> Not supported by the latest release and might be lacking features
|
||||
* <code>❌</code> Not supported at all
|
||||
* <code>❓</code> Unknown or untested
|
||||
|
||||
Remarks:
|
||||
* 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.
|
||||
* Oculus support is only provided through the recommended Android NDK r21b by Epic Games.
|
||||
* Supporting Unreal Engine 4.22 through 4.24 for Oculus development is a huge challenge due to limited Android NDK support (r14b to r18b); firstly, because of uncomplete C++11 standard library support, and second, as a result of a known bug in Unreal Engine, which falsely detects NDK r18b as unsupported r18c. Thus, only Unreal Engine 4.25+ support is provided for Android/Oculus development. Third, [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, which is the recommended NDK by Epic Games for 4.22 to 4.24 cannot build the serial library.
|
||||
* Oculus 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, 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.
|
||||
|
||||
## Documentation
|
||||
## Changelog
|
||||
|
||||
We maintain [a detailed changelog for this project](CHANGELOG.md) as well. Please consult the changelog before upgrading to any newer release.
|
||||
|
||||
## Documentation
|
||||
|
||||
The Blueprints documentation will be coming soon.
|
||||
[The Blueprints documentation is hosted on SenseGlove Docs](https://senseglove.gitlab.io/unreal-blueprint-docs/).
|
||||
|
||||
For the C++ documentation, since this plugin builds on top of [SGConnect](https://senseglove.gitlab.io/SenseGloveDocs/native/core-api-intro.html#sgconnect) and [SGCoreCpp](https://senseglove.gitlab.io/SenseGloveDocs/native/core-api-intro.html#sgcorecpp) third-party C++ libraries, please refer to [the upstream documentation](https://senseglove.gitlab.io/SenseGloveDocs/native/cpp-reference.html).
|
||||
|
||||
@@ -65,33 +64,43 @@ Source
|
||||
│
|
||||
├── SenseGlove (the UE-specific high-level API)
|
||||
│
|
||||
├── SenseGloveBuildHacks (uses Excepttions and RTTI, internally used for compiler-specific build hacks)
|
||||
├── SenseGloveAndroid (the Android-specific module)
|
||||
│
|
||||
├── SenseGloveConnect (exposes part of the SGConnect low-level API to C++ and Blueprints)
|
||||
├── SenseGloveBuildHacks (uses Exceptions and RTTI, internally used for compiler-specific build hacks)
|
||||
│
|
||||
├── SenseGloveConnectImpl (uses Excepttions and RTTI, intended for internal use only)
|
||||
├── SenseGloveConnect (exposes part of the SGConnect low-level API to C++)
|
||||
│
|
||||
├── SenseGloveConnectImpl (uses Exceptions and RTTI, intended for internal use only)
|
||||
│
|
||||
├── SenseGloveConnectKismet (SGConnect functionality exposed to Blueprints)
|
||||
│
|
||||
├── SenseGloveCore (exposes part of the SGCoreCpp low-level API to C++ and Blueprints)
|
||||
├── SenseGloveCore (exposes part of the SGCoreCpp low-level API to C++)
|
||||
│
|
||||
├── SenseGloveCoreImpl (uses Excepttions and RTTI, intended for internal use only)
|
||||
├── SenseGloveCoreImpl (uses Exceptions and RTTI, intended for internal use only)
|
||||
│
|
||||
├── SenseGloveCoreKismet (SGCoreCpp functionality exposed to Blueprints)
|
||||
│
|
||||
├── SenseGloveCoreTypes (exposes special public types from the SenseGloveCore module in order to be shared by with other modules)
|
||||
│
|
||||
├── SenseGloveEditor (the Editor module)
|
||||
│
|
||||
├── SenseGloveInterop (internally used for interoperability between RTTI disabled/enabled modules)
|
||||
│
|
||||
├── SenseGloveKismet(exposes Blueprints-specific functionality from the SenseGlove module)
|
||||
├── SenseGloveKismet (exposes Blueprints-specific functionality from the SenseGlove module)
|
||||
│
|
||||
├── SenseGloveLog (the internal log module)
|
||||
│
|
||||
├── SenseGloveTypes (exposes various enums from the backend libraries)
|
||||
├── SenseGloveSettings (the plugin's settings manager)
|
||||
│
|
||||
├── SenseGloveSettingsKismet (exposes Blueprints-specific functionality from the SenseGloveSettings module)
|
||||
│
|
||||
├── SenseGloveTypes (exposes various enums from the backend libraries and also types from the SenseGlove module)
|
||||
│
|
||||
├── SenseGloveUtils (the internal utility module)
|
||||
│
|
||||
└── ThirdParty (3rd-party dependencies)
|
||||
│
|
||||
├── android (.jar file Java libraries for Android)
|
||||
│
|
||||
├── include (header files)
|
||||
│ │
|
||||
@@ -106,52 +115,90 @@ Source
|
||||
│ └── serial
|
||||
│
|
||||
└── lib (platform-specific pre-built binary dependencies)
|
||||
│
|
||||
├── android
|
||||
│ │
|
||||
│ ├── r21e (Android NDK r21e dependencies for UE 4.27 and 5.0)
|
||||
│ │ │
|
||||
│ │ │
|
||||
│ │ ├── arm64 (64-bit Arm variant of Android)
|
||||
│ │ │ │
|
||||
│ │ │ ├── debug
|
||||
│ │ │ │
|
||||
│ │ │ └── release
|
||||
│ │ │
|
||||
│ │ ├── armv7 (32-bit ARM variant of Android)
|
||||
│ │ │ │
|
||||
│ │ │ ├── debug
|
||||
│ │ │ │
|
||||
│ │ │ └── release
|
||||
│ │ │
|
||||
│ │ ├── x64 (64-bit x86-64 variant of Android)
|
||||
│ │ │ │
|
||||
│ │ │ ├── debug
|
||||
│ │ │ │
|
||||
│ │ │ └── release
|
||||
│ │ │
|
||||
│ │ └── x86 (32-bit x86 variant of Android)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ └── r25b (Android NDK r21b dependencies for UE 5.1)
|
||||
│ │
|
||||
│ │
|
||||
│ ├── arm64 (64-bit Arm variant of Android)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ ├── armv7 (32-bit ARM variant of Android)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ ├── x64 (64-bit x86-64 variant of Android)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ └── x86 (32-bit x86 variant of Android)
|
||||
│ │
|
||||
│ ├── debug
|
||||
│ │
|
||||
│ └── release
|
||||
│
|
||||
├── linux
|
||||
│ │
|
||||
│ ├── v13 (UE 4.22 Linux dependencies)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ ├── v15 (UE 4.23 and 4.24 Linux dependencies)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ ├── v16 (UE 4.25 Linux dependencies)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ ├── v17 (UE 4.26 Linux dependencies)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ ├── v19 (UE 4.27 Linux dependencies)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ └── v20 (UE 5.0 Linux dependencies)
|
||||
│ ├── v20 (UE 5.0 and 5.1 Linux dependencies)
|
||||
│ │ │
|
||||
│ │ ├── debug
|
||||
│ │ │
|
||||
│ │ └── release
|
||||
│ │
|
||||
│ └── v21 (UE 5.2 Linux dependencies)
|
||||
│ │
|
||||
│ ├── debug
|
||||
│ │
|
||||
│ └── release
|
||||
│
|
||||
├── oculus
|
||||
│ │
|
||||
│ ├── debug
|
||||
│ │
|
||||
│ └── release
|
||||
│
|
||||
└── win64
|
||||
│
|
||||
├── msvc141 (Microsoft Visual Studio 2017 dependencies)
|
||||
│ │
|
||||
│ ├── debug
|
||||
│ │
|
||||
│ └── release
|
||||
│
|
||||
├── msvc142 (Microsoft Visual Studio 2019 dependencies)
|
||||
│ │
|
||||
|
||||
+71
-17
@@ -1,20 +1,21 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0.0",
|
||||
"VersionName": "1.2.1",
|
||||
"FriendlyName": "SenseGlove",
|
||||
"Description": "Integrating the SenseGlove haptic controller into Unreal Engine",
|
||||
"Category": "Virtual Reality",
|
||||
"CreatedBy": "SenseGlove",
|
||||
"CreatedByURL": "https://www.senseglove.com/",
|
||||
"DocsURL": "",
|
||||
"MarketplaceURL": "",
|
||||
"DocsURL": "https://senseglove.gitlab.io/unreal-blueprint-docs/",
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/5e1d408f517b4966a269ec1035de0b9e",
|
||||
"SupportURL": "https://www.senseglove.com/support/",
|
||||
"CanContainContent": true,
|
||||
"IsBetaVersion": false,
|
||||
"IsExperimentalVersion": false,
|
||||
"Installed": false,
|
||||
"SupportedTargetPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
],
|
||||
@@ -24,6 +25,17 @@
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "SenseGloveAndroid",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -31,8 +43,9 @@
|
||||
{
|
||||
"Name": "SenseGloveBuildHacks",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -40,8 +53,9 @@
|
||||
{
|
||||
"Name": "SenseGloveConnect",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -49,8 +63,9 @@
|
||||
{
|
||||
"Name": "SenseGloveConnectImpl",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -58,8 +73,9 @@
|
||||
{
|
||||
"Name": "SenseGloveConnectKismet",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -67,8 +83,9 @@
|
||||
{
|
||||
"Name": "SenseGloveCore",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -76,8 +93,9 @@
|
||||
{
|
||||
"Name": "SenseGloveCoreImpl",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -85,16 +103,27 @@
|
||||
{
|
||||
"Name": "SenseGloveCoreKismet",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "SenseGloveCoreTypes",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "SenseGloveEditor",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "PostEngineInit",
|
||||
"WhitelistPlatforms": [
|
||||
"Linux",
|
||||
"Win64"
|
||||
@@ -103,8 +132,9 @@
|
||||
{
|
||||
"Name": "SenseGloveInterop",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -112,8 +142,9 @@
|
||||
{
|
||||
"Name": "SenseGloveKismet",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -121,8 +152,29 @@
|
||||
{
|
||||
"Name": "SenseGloveLog",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "SenseGloveSettings",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "SenseGloveSettingsKismet",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -130,8 +182,9 @@
|
||||
{
|
||||
"Name": "SenseGloveTypes",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
@@ -139,8 +192,9 @@
|
||||
{
|
||||
"Name": "SenseGloveUtils",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"Win64"
|
||||
]
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
|
||||
|
||||
USGVirtualHandAnimInstance::USGVirtualHandAnimInstance(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
FSGVirtualHandAnimInstanceProxy* USGVirtualHandAnimInstance::CreateAnimInstanceProxy()
|
||||
{
|
||||
return new FSGVirtualHandAnimInstanceProxy();
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h"
|
||||
|
||||
#include "BoneContainer.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "BonePose.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Math/Rotator.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
|
||||
#include "SenseGlove/Components/SGVirtualHandComponent.h"
|
||||
|
||||
FSGVirtualHandAnimInstanceProxy::FSGVirtualHandAnimInstanceProxy()
|
||||
: FAnimInstanceProxy()
|
||||
{
|
||||
}
|
||||
|
||||
FSGVirtualHandAnimInstanceProxy::FSGVirtualHandAnimInstanceProxy(UAnimInstance* Instance)
|
||||
: FAnimInstanceProxy(Instance)
|
||||
{
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::PreEvaluateAnimation(UAnimInstance* InAnimInstance)
|
||||
{
|
||||
FAnimInstanceProxy::PreEvaluateAnimation(InAnimInstance);
|
||||
|
||||
if (!IsValid(InAnimInstance))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
USGVirtualHandComponent* VirtualHand{Cast<USGVirtualHandComponent>(GetSkelMeshComponent())};
|
||||
if (!IsValid(VirtualHand))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BonesRotations.Empty();
|
||||
|
||||
if (!VirtualHand->IsGloveConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BonesRotations = VirtualHand->GetFingersBonesRotations();
|
||||
}
|
||||
|
||||
bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
{
|
||||
USGVirtualHandComponent* VirtualHand{Cast<USGVirtualHandComponent>(GetSkelMeshComponent())};
|
||||
if (!IsValid(VirtualHand) && !VirtualHand->IsGloveConnected())
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
const USkeletalMesh* HandMesh{VirtualHand->
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1
|
||||
GetSkeletalMeshAsset()
|
||||
#else /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
|
||||
SkeletalMesh
|
||||
#endif /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
|
||||
};
|
||||
if (!IsValid(HandMesh))
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
const USkeleton* HandSkeleton{HandMesh->GetSkeleton()};
|
||||
if (!IsValid(HandSkeleton))
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
FComponentSpacePoseContext PoseContext{Output.AnimInstanceProxy};
|
||||
PoseContext.Pose.InitPose(Output.Pose);
|
||||
|
||||
for (const TTuple<FName, FRotator>& Bone: BonesRotations)
|
||||
{
|
||||
FName BoneName{Bone.Key};
|
||||
FRotator BoneRotation{Bone.Value};
|
||||
|
||||
const int32 BoneIndex = GetRequiredBones().GetPoseBoneIndexForBoneName(BoneName);
|
||||
if (BoneIndex == INDEX_NONE)
|
||||
{
|
||||
SGLOG_WARNING(FString::Printf(TEXT("Could not find a bone index for '%s' finger bone!"),
|
||||
*BoneName.ToString()));
|
||||
continue;
|
||||
}
|
||||
|
||||
FBoneReference BoneReference;
|
||||
BoneReference.BoneName = MoveTemp(BoneName);
|
||||
BoneReference.BoneIndex = BoneIndex;
|
||||
BoneReference.bUseSkeletonIndex = true;
|
||||
|
||||
FAnimNode_ModifyBone BoneController;
|
||||
BoneController.BoneToModify = MoveTemp(BoneReference);
|
||||
BoneController.Rotation = MoveTemp(BoneRotation);
|
||||
BoneController.RotationMode = EBoneModificationMode::BMM_Replace;
|
||||
BoneController.RotationSpace = EBoneControlSpace::BCS_ParentBoneSpace;
|
||||
BoneController.ScaleMode = EBoneModificationMode::BMM_Ignore;
|
||||
BoneController.TranslationMode = EBoneModificationMode::BMM_Ignore;
|
||||
|
||||
if (BoneController.IsValidToEvaluate(HandSkeleton, Output.Pose.GetBoneContainer()))
|
||||
{
|
||||
TArray<FBoneTransform> BoneTransforms;
|
||||
BoneController.EvaluateSkeletalControl_AnyThread(PoseContext, BoneTransforms);
|
||||
|
||||
const TArray<FBoneTransform>::SizeType BoneTransformsNum = BoneTransforms.Num();
|
||||
if (BoneTransformsNum > 0)
|
||||
{
|
||||
PoseContext.Pose.LocalBlendCSBoneTransforms(BoneTransforms, 1.0f);
|
||||
PoseContext.Pose.ConvertComponentPosesToLocalPoses(PoseContext.Pose, Output.Pose);
|
||||
|
||||
VirtualHand->MarkRenderStateDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,686 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/Components/SGVirtualHandComponent.h"
|
||||
|
||||
#include "Animation/Skeleton.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "UObject/ConstructorHelpers.h"
|
||||
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
|
||||
#include "SGConnect/SGConnect.h"
|
||||
#include "SGCore/SGDeviceList.h"
|
||||
#include "SGCore/SGHandPose.h"
|
||||
#include "SGCore/SGHapticGlove.h"
|
||||
#include "SGCore/SGHapticGloveHandProfiles.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
|
||||
struct USGVirtualHandComponent::FImpl
|
||||
{
|
||||
/************************
|
||||
* Static methods
|
||||
************************/
|
||||
|
||||
FORCEINLINE static const FString& GetDefaultLeftHandMeshPath()
|
||||
{
|
||||
static const FString Path{TEXT("SkeletalMesh'/SenseGlove/Meshes/"
|
||||
"SK_SenseGlove_VirtualHand_Left.SK_SenseGlove_VirtualHand_Left'")};
|
||||
return Path;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FString& GetDefaultLeftHandMeshPathOnly()
|
||||
{
|
||||
static const FString Path{TEXT("/SenseGlove/Meshes/"
|
||||
"SK_SenseGlove_VirtualHand_Left.SK_SenseGlove_VirtualHand_Left")};
|
||||
return Path;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FString& GetDefaultRightHandMeshPath()
|
||||
{
|
||||
static const FString Path{TEXT("SkeletalMesh'/SenseGlove/Meshes/"
|
||||
"SK_SenseGlove_VirtualHand_Right.SK_SenseGlove_VirtualHand_Right'")};
|
||||
return Path;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FString& GetDefaultRightHandMeshPathOnly()
|
||||
{
|
||||
static const FString Path{TEXT("/SenseGlove/Meshes/"
|
||||
"SK_SenseGlove_VirtualHand_Right.SK_SenseGlove_VirtualHand_Right")};
|
||||
return Path;
|
||||
}
|
||||
|
||||
/************************
|
||||
* Owner object
|
||||
************************/
|
||||
|
||||
USGVirtualHandComponent* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(USGVirtualHandComponent* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
|
||||
bool IsEditor() const;
|
||||
|
||||
FString GetDefaultMeshPath() const;
|
||||
bool IsUsingUserMesh() const;
|
||||
USkeletalMesh* LoadDefaultMesh() const;
|
||||
void SetDefaultMesh() const;
|
||||
|
||||
USkeletalMesh* GetMesh() const;
|
||||
USkeleton* GetSkeleton() const;
|
||||
const FReferenceSkeleton& GetRefSkeleton() const;
|
||||
|
||||
bool InitializeBackend() const;
|
||||
bool UninitializeBackend() const;
|
||||
bool CheckGlove() const;
|
||||
|
||||
void SetVisibility(bool bInVisible) const;
|
||||
};
|
||||
|
||||
const TArray<TArray<FName>>& USGVirtualHandComponent::GetLeftHandFingerBoneNames()
|
||||
{
|
||||
static const TArray<TArray<FName>> BoneNames{
|
||||
{FName(TEXT("thumb_01_l")), FName(TEXT("thumb_02_l")), FName(TEXT("thumb_03_l"))},
|
||||
{FName(TEXT("index_01_l")), FName(TEXT("index_02_l")), FName(TEXT("index_03_l"))},
|
||||
{FName(TEXT("middle_01_l")), FName(TEXT("middle_02_l")), FName(TEXT("middle_03_l"))},
|
||||
{FName(TEXT("ring_01_l")), FName(TEXT("ring_02_l")), FName(TEXT("ring_03_l"))},
|
||||
{FName(TEXT("pinky_01_l")), FName(TEXT("pinky_02_l")), FName(TEXT("pinky_03_l"))},
|
||||
};
|
||||
return BoneNames;
|
||||
}
|
||||
|
||||
const TArray<TArray<FName>>& USGVirtualHandComponent::GetRightHandFingerBoneNames()
|
||||
{
|
||||
static const TArray<TArray<FName>> BoneNames{
|
||||
{FName(TEXT("thumb_01_r")), FName(TEXT("thumb_02_r")), FName(TEXT("thumb_03_r"))},
|
||||
{FName(TEXT("index_01_r")), FName(TEXT("index_02_r")), FName(TEXT("index_03_r"))},
|
||||
{FName(TEXT("middle_01_r")), FName(TEXT("middle_02_r")), FName(TEXT("middle_03_r"))},
|
||||
{FName(TEXT("ring_01_r")), FName(TEXT("ring_02_r")), FName(TEXT("ring_03_r"))},
|
||||
{FName(TEXT("pinky_01_r")), FName(TEXT("pinky_02_r")), FName(TEXT("pinky_03_r"))},
|
||||
};
|
||||
return BoneNames;
|
||||
}
|
||||
|
||||
const FName& USGVirtualHandComponent::GetLeftHandFingerBoneName(const int32 Finger, const int32 Joint)
|
||||
{
|
||||
const TArray<TArray<FName>>& BoneNames{GetLeftHandFingerBoneNames()};
|
||||
|
||||
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
|
||||
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
|
||||
|
||||
const FName& BoneName{BoneNames[Finger][Joint]};
|
||||
return BoneName;
|
||||
}
|
||||
|
||||
const FName& USGVirtualHandComponent::GetRightHandFingerBoneName(const int32 Finger, const int32 Joint)
|
||||
{
|
||||
const TArray<TArray<FName>>& BoneNames{GetRightHandFingerBoneNames()};
|
||||
|
||||
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
|
||||
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
|
||||
|
||||
const FName& BoneName{BoneNames[Finger][Joint]};
|
||||
return BoneName;
|
||||
}
|
||||
|
||||
USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
{
|
||||
PrimaryComponentTick.bTickEvenWhenPaused = false;
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
PrimaryComponentTick.bStartWithTickEnabled = true;
|
||||
bTickInEditor = true;
|
||||
bNeverNeedsRenderUpdate = false;
|
||||
bAllowConcurrentTick = true;
|
||||
SetUpdateAnimationInEditor(true);
|
||||
|
||||
SetCastShadow(true);
|
||||
SetCastHiddenShadow(false);
|
||||
bCastDynamicShadow = true;
|
||||
SetOnlyOwnerSee(false);
|
||||
SetReceivesDecals(true);
|
||||
SetCanEverAffectNavigation(false);
|
||||
Super::SetCollisionObjectType(ECC_WorldDynamic);
|
||||
Super::SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
||||
Super::SetCollisionResponseToAllChannels(ECR_Overlap);
|
||||
Super::SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
|
||||
Super::SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Block);
|
||||
Super::SetCollisionResponseToChannel(ECC_Pawn, ECR_Block);
|
||||
Super::SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
Super::SetCollisionResponseToChannel(ECC_PhysicsBody, ECR_Block);
|
||||
Super::SetCollisionResponseToChannel(ECC_Vehicle, ECR_Block);
|
||||
Super::SetCollisionResponseToChannel(ECC_Destructible, ECR_Block);
|
||||
|
||||
Super::SetAnimClass(USGVirtualHandAnimInstance::StaticClass());
|
||||
|
||||
bRight = true;
|
||||
bHiddenInGameIfNoGloveDetected = false;
|
||||
|
||||
Super::SetSkeletalMesh(nullptr, true);
|
||||
|
||||
bBackendInitialized = false;
|
||||
Glove = nullptr;
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::SetRight(const bool bInRight)
|
||||
{
|
||||
bRight = bInRight;
|
||||
|
||||
if (!Pimpl->IsUsingUserMesh())
|
||||
{
|
||||
Pimpl->SetDefaultMesh();
|
||||
}
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::SetAnimClass(UClass* NewClass)
|
||||
{
|
||||
ensureAlwaysMsgf(Cast<USGVirtualHandAnimInstance>(NewClass),
|
||||
TEXT("The AnimInstance class must be a subclass of USGVirtualHandAnimInstance!"));
|
||||
|
||||
Super::SetAnimClass(NewClass);
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::PostInitProperties()
|
||||
{
|
||||
Super::PostInitProperties();
|
||||
|
||||
if (!Pimpl->IsUsingUserMesh())
|
||||
{
|
||||
Pimpl->SetDefaultMesh();
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void USGVirtualHandComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
const FName PropertyName{
|
||||
PropertyChangedEvent.Property
|
||||
? PropertyChangedEvent.Property->GetFName()
|
||||
: NAME_None
|
||||
};
|
||||
if (PropertyName == GET_MEMBER_NAME_CHECKED(USGVirtualHandComponent, bRight))
|
||||
{
|
||||
if (!Pimpl->IsUsingUserMesh())
|
||||
{
|
||||
Pimpl->SetDefaultMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
void USGVirtualHandComponent::InitializeComponent()
|
||||
{
|
||||
Super::InitializeComponent();
|
||||
|
||||
if (!Pimpl->IsUsingUserMesh())
|
||||
{
|
||||
Pimpl->SetDefaultMesh();
|
||||
}
|
||||
|
||||
if (Pimpl->InitializeBackend())
|
||||
{
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::UninitializeComponent()
|
||||
{
|
||||
Super::UninitializeComponent();
|
||||
|
||||
(void) Pimpl->UninitializeBackend();
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (Pimpl->InitializeBackend())
|
||||
{
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
Super::EndPlay(EndPlayReason);
|
||||
|
||||
(void) Pimpl->UninitializeBackend();
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::TickComponent(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (Pimpl->IsEditor())
|
||||
{
|
||||
EditorTick(DeltaTime, TickType, ThisTickFunction);
|
||||
return;
|
||||
}
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool bReinitPose)
|
||||
{
|
||||
if (IsValid(NewMesh))
|
||||
{
|
||||
Super::SetSkeletalMesh(NewMesh, bReinitPose);
|
||||
}
|
||||
else
|
||||
{
|
||||
Super::SetSkeletalMesh(Pimpl->LoadDefaultMesh(), bReinitPose);
|
||||
}
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::EditorTick(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
bool USGVirtualHandComponent::IsGloveConnected() const
|
||||
{
|
||||
return Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
USGHandPose* USGVirtualHandComponent::GetHandPose()
|
||||
{
|
||||
USGHandPose* HandPose{nullptr};
|
||||
|
||||
if (IsValid(Glove))
|
||||
{
|
||||
#if ! PLATFORM_ANDROID
|
||||
Glove->GetHandPose(this, HandPose);
|
||||
#else /* ! PLATFORM_ANDROID */
|
||||
const UWorld* World{GetWorld()};
|
||||
const float DeltaTime = UGameplayStatics::GetWorldDeltaSeconds(World);
|
||||
Glove->GetHandPose(this, DeltaTime, HandPose);
|
||||
#endif /* ! PLATFORM_ANDROID */
|
||||
}
|
||||
|
||||
return HandPose;
|
||||
}
|
||||
|
||||
const FName& USGVirtualHandComponent::GetFingerBoneName(const int32 Finger, const int32 Joint) const
|
||||
{
|
||||
const FName& Name{
|
||||
IsRight()
|
||||
? GetRightHandFingerBoneName(Finger, Joint)
|
||||
: GetLeftHandFingerBoneName(Finger, Joint)
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
const FTransform& USGVirtualHandComponent::GetFingerBoneRefTransform(const int32 Finger, const int32 Joint) const
|
||||
{
|
||||
const FName& BoneName{GetFingerBoneName(Finger, Joint)};
|
||||
const FReferenceSkeleton& ReferenceSkeleton{Pimpl->GetRefSkeleton()};
|
||||
const int32 BoneIndex = ReferenceSkeleton.FindBoneIndex(BoneName);
|
||||
|
||||
if (BoneIndex == INDEX_NONE)
|
||||
{
|
||||
SGLOG_WARNING(FString::Printf(TEXT("Could not find a bone index for '%s' finger bone!"),
|
||||
*BoneName.ToString()));
|
||||
return FTransform::Identity;
|
||||
}
|
||||
|
||||
const FTransform& BoneTransform{ReferenceSkeleton.GetRefBonePose()[BoneIndex]};
|
||||
return BoneTransform;
|
||||
}
|
||||
|
||||
FRotator USGVirtualHandComponent::GetFingerBoneRefRotation(const int32 Finger, const int32 Joint) const
|
||||
{
|
||||
const FTransform BoneTransform{GetFingerBoneRefTransform(Finger, Joint)};
|
||||
FRotator BoneRotation{BoneTransform.GetRotation().Rotator()};
|
||||
return MoveTemp(BoneRotation);
|
||||
}
|
||||
|
||||
TMap<FName, FRotator> USGVirtualHandComponent::GetFingersBonesRotations()
|
||||
{
|
||||
TMap<FName, FRotator> Rotations;
|
||||
|
||||
if (!IsGloveConnected())
|
||||
{
|
||||
return MoveTemp(Rotations);
|
||||
}
|
||||
|
||||
const USGHandPose* HandPose = GetHandPose();
|
||||
if (!IsValid(HandPose))
|
||||
{
|
||||
return MoveTemp(Rotations);
|
||||
}
|
||||
|
||||
const TArray<TArray<FVector>> HandAngles{HandPose->GetHandAngles()};
|
||||
|
||||
for (int32 FingerIndex = 0; FingerIndex < HandAngles.Num(); ++FingerIndex)
|
||||
{
|
||||
const TArray<FVector>& FingerJointAngles{HandAngles[FingerIndex]};
|
||||
|
||||
for (int32 JointIndex = 0; JointIndex < FingerJointAngles.Num(); ++JointIndex)
|
||||
{
|
||||
const FVector& JointAngle{FingerJointAngles[JointIndex]};
|
||||
const FQuat JointRotation{FQuat::MakeFromEuler(JointAngle)};
|
||||
|
||||
const FTransform& BoneRefTransform{GetFingerBoneRefTransform(FingerIndex, JointIndex)};
|
||||
|
||||
FQuat NewBoneRotation{BoneRefTransform.GetRotation() * JointRotation};
|
||||
|
||||
FName BoneName{GetFingerBoneName(FingerIndex, JointIndex)};
|
||||
|
||||
Rotations.Emplace(MoveTemp(BoneName), MoveTemp(NewBoneRotation));
|
||||
}
|
||||
}
|
||||
|
||||
return MoveTemp(Rotations);
|
||||
}
|
||||
|
||||
USGVirtualHandComponent::FImpl::FImpl(USGVirtualHandComponent* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
USGVirtualHandComponent::FImpl::~FImpl() = default;
|
||||
|
||||
bool USGVirtualHandComponent::FImpl::IsEditor() const
|
||||
{
|
||||
const UWorld* World{Owner->GetWorld()};
|
||||
if (World && (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::EditorPreview))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FString USGVirtualHandComponent::FImpl::GetDefaultMeshPath() const
|
||||
{
|
||||
FString SkeletalMeshPath;
|
||||
|
||||
if (Owner->IsRight())
|
||||
{
|
||||
SkeletalMeshPath = GetDefaultRightHandMeshPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
SkeletalMeshPath = GetDefaultLeftHandMeshPath();
|
||||
}
|
||||
|
||||
return MoveTemp(SkeletalMeshPath);
|
||||
}
|
||||
|
||||
bool USGVirtualHandComponent::FImpl::IsUsingUserMesh() const
|
||||
{
|
||||
const USkeletalMesh* CurrentMesh{GetMesh()};
|
||||
if (!IsValid(CurrentMesh))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FString CurrentMeshPath(CurrentMesh->GetPathName());
|
||||
const FString LeftHandDefaultMeshPath(GetDefaultLeftHandMeshPath());
|
||||
const FString LeftHandDefaultMeshPathOnly(GetDefaultLeftHandMeshPathOnly());
|
||||
const FString RightHandDefaultMeshPath(GetDefaultRightHandMeshPath());
|
||||
const FString RightHandDefaultMeshPathOnly(GetDefaultRightHandMeshPathOnly());
|
||||
if (CurrentMeshPath == LeftHandDefaultMeshPath
|
||||
|| CurrentMeshPath == LeftHandDefaultMeshPathOnly
|
||||
|| CurrentMeshPath == RightHandDefaultMeshPath
|
||||
|| CurrentMeshPath == RightHandDefaultMeshPathOnly)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
USkeletalMesh* USGVirtualHandComponent::FImpl::LoadDefaultMesh() const
|
||||
{
|
||||
const FString DefaultMeshPath{GetDefaultMeshPath()};
|
||||
USkeletalMesh* DefaultMesh{
|
||||
Cast<USkeletalMesh>(StaticLoadObject(USkeletalMesh::StaticClass(), nullptr, *DefaultMeshPath))
|
||||
};
|
||||
|
||||
if (!IsValid(DefaultMesh))
|
||||
{
|
||||
SGLOG_WARNING(FString::Printf(TEXT("Failed to load the default skeletal mesh: '%s'"), *DefaultMeshPath));
|
||||
}
|
||||
|
||||
return DefaultMesh;
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::FImpl::SetDefaultMesh() const
|
||||
{
|
||||
Owner->SetSkeletalMesh(LoadDefaultMesh(), true);
|
||||
}
|
||||
|
||||
USkeletalMesh* USGVirtualHandComponent::FImpl::GetMesh() const
|
||||
{
|
||||
return Owner->
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1
|
||||
GetSkeletalMeshAsset()
|
||||
#else /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
|
||||
SkeletalMesh
|
||||
#endif /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
|
||||
;
|
||||
}
|
||||
|
||||
USkeleton* USGVirtualHandComponent::FImpl::GetSkeleton() const
|
||||
{
|
||||
USkeletalMesh* Mesh{GetMesh()};
|
||||
ensureAlwaysMsgf(IsValid(Mesh), TEXT("Invalid SkeletalMesh object!"));
|
||||
return Mesh->GetSkeleton();
|
||||
}
|
||||
|
||||
const FReferenceSkeleton& USGVirtualHandComponent::FImpl::GetRefSkeleton() const
|
||||
{
|
||||
const USkeletalMesh* Mesh{GetMesh()};
|
||||
ensureAlwaysMsgf(IsValid(Mesh), TEXT("Invalid SkeletalMesh object!"));
|
||||
return Mesh->GetRefSkeleton();
|
||||
}
|
||||
|
||||
bool USGVirtualHandComponent::FImpl::InitializeBackend() const
|
||||
{
|
||||
if (!Owner->bBackendInitialized)
|
||||
{
|
||||
#if PLATFORM_ANDROID
|
||||
const int32_t Result = FSGConnect::Init();
|
||||
switch (Result)
|
||||
{
|
||||
case -3:
|
||||
SGLOG_ERROR("An Unexpected error occurred. Please try again.");
|
||||
return false;
|
||||
case -2:
|
||||
SGLOG_ERROR("Device Scanning is already running within a different program.");
|
||||
return false;
|
||||
case -1:
|
||||
SGLOG_ERROR("Device Scanning already being initialized (function called twice in short succession).");
|
||||
return false;
|
||||
case 0:
|
||||
// Do not pollute the logs!
|
||||
//SGLOG_ERROR("Device Scanning is already running within this program.");
|
||||
// We must return here in case there are two virtual hand components are present in the scene.
|
||||
return true;
|
||||
case 1:
|
||||
SGLOG("Successfully started up DeviceScanning from the current program.");
|
||||
break;
|
||||
default:
|
||||
ensureAlwaysMsgf(false, TEXT("Unhandled Init return status code!"));
|
||||
return false;
|
||||
}
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
// Ensure that the device list is empty before doing anything.
|
||||
FSGDeviceList::Dispose();
|
||||
FSGDeviceList::Reinitialize();
|
||||
|
||||
// Load the latest hand profiles.
|
||||
FSGHapticGloveHandProfiles::TryLoadingFromDisk();
|
||||
|
||||
Owner->bBackendInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USGVirtualHandComponent::FImpl::UninitializeBackend() const
|
||||
{
|
||||
// NOTE
|
||||
// In Editor builds we should be avoiding dispose, since stopping the game in PIE mode, causes the virtual-hand
|
||||
// to disappear in the editor as the plugin won't be able to retrieve the glove status anymore.
|
||||
#if ! WITH_EDITOR
|
||||
if (Owner->bBackendInitialized)
|
||||
{
|
||||
FSGDeviceList::Dispose();
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
const int32_t Result = FSGConnect::Dispose();
|
||||
switch (Result)
|
||||
{
|
||||
case -3:
|
||||
SGLOG_ERROR("An Unexpected error occurred. Please try again.");
|
||||
return false;
|
||||
case -2:
|
||||
SGLOG_ERROR("Not allowed to dispose of Device Scanning because this is not the program which started it.");
|
||||
return false;
|
||||
case -1:
|
||||
SGLOG_ERROR("Device Scanning is currently being disposed off. This takes a second or two. (function called twice in short succession).");
|
||||
return false;
|
||||
case 0:
|
||||
SGLOG_ERROR("There is no deviceScanner running from any program, so disposing is skipped.");
|
||||
return false;
|
||||
case 1:
|
||||
SGLOG("Successfully disposed of DeviceScanner resources.");
|
||||
break;
|
||||
default:
|
||||
ensureAlwaysMsgf(false, TEXT("Unhandled Dispose return status code!"));
|
||||
return false;
|
||||
}
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
Owner->bBackendInitialized = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* ! WITH_EDITOR */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USGVirtualHandComponent::FImpl::CheckGlove() const
|
||||
{
|
||||
if (!Owner->bBackendInitialized)
|
||||
{
|
||||
const bool bSucceeded = InitializeBackend();
|
||||
if (!bSucceeded)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool bGloveWasPresent = IsValid(Owner->Glove);
|
||||
const bool bFoundGlove = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
|
||||
|
||||
if (!bFoundGlove && bGloveWasPresent)
|
||||
{
|
||||
SGLOG_ERROR(FString::Printf(TEXT("Could not find a %s glove!"),
|
||||
(Owner->IsRight() ? TEXT("right-handed") : TEXT("left-handed"))));
|
||||
}
|
||||
|
||||
const bool bIsEditor = IsEditor();
|
||||
if (!bIsEditor)
|
||||
{
|
||||
const bool bIsVisible = Owner->IsVisible();
|
||||
if (Owner->bHiddenInGameIfNoGloveDetected)
|
||||
{
|
||||
if (bFoundGlove)
|
||||
{
|
||||
if (!bIsVisible)
|
||||
{
|
||||
SetVisibility(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bIsVisible)
|
||||
{
|
||||
SetVisibility(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!bIsVisible)
|
||||
{
|
||||
SetVisibility(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bFoundGlove;
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::FImpl::SetVisibility(const bool bInVisible) const
|
||||
{
|
||||
Owner->SetVisibility(bInVisible, true);
|
||||
}
|
||||
|
||||
void USGVirtualHandComponent::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
@@ -0,0 +1,776 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
|
||||
#include "Animation/Skeleton.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "UObject/ConstructorHelpers.h"
|
||||
|
||||
#include "SGConnect/SGConnect.h"
|
||||
#include "SGCore/SGDeviceList.h"
|
||||
#include "SGCore/SGHapticGlove.h"
|
||||
#include "SGCore/SGHapticGloveHandProfiles.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
#include "SGSettings/SGSettings.h"
|
||||
|
||||
struct USGWristTrackerComponent::FImpl
|
||||
{
|
||||
/************************
|
||||
* Static methods
|
||||
************************/
|
||||
|
||||
/************************
|
||||
* Owner object
|
||||
************************/
|
||||
|
||||
USGWristTrackerComponent* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(USGWristTrackerComponent* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
|
||||
bool IsEditor() const;
|
||||
|
||||
bool InitializeBackend() const;
|
||||
bool UninitializeBackend() const;
|
||||
bool CheckGlove() const;
|
||||
|
||||
void UpdateWristTrackingData() const;
|
||||
void DrawDebugGizmo();
|
||||
};
|
||||
|
||||
USGWristTrackerComponent::USGWristTrackerComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
{
|
||||
PrimaryComponentTick.bTickEvenWhenPaused = false;
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
PrimaryComponentTick.bStartWithTickEnabled = true;
|
||||
bTickInEditor = true;
|
||||
bNeverNeedsRenderUpdate = true;
|
||||
bAllowConcurrentTick = true;
|
||||
|
||||
SetCastShadow(false);
|
||||
SetCastHiddenShadow(false);
|
||||
bCastDynamicShadow = false;
|
||||
SetOnlyOwnerSee(false);
|
||||
SetReceivesDecals(false);
|
||||
SetCanEverAffectNavigation(false);
|
||||
|
||||
SetRight(true);
|
||||
|
||||
bOverridePluginWristTrackingSettings = false;
|
||||
bDrawDebugWristTrackerGizmo = false;
|
||||
TrackingHardware = ESGPositionalTrackingHardware::None;
|
||||
TrackingHardwareLocationOffset = FVector::ZeroVector;
|
||||
TrackingHardwareLocationOffset = FVector::ZeroVector;
|
||||
|
||||
bOverridePluginWristTrackingDebugSettings = false;
|
||||
bDrawDebugWristTrackerGizmo = false;
|
||||
DebugWristTrackerGizmoLength = 1.0f;
|
||||
DebugWristTrackerGizmoXAxisColor = FColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
DebugWristTrackerGizmoYAxisColor = FColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
DebugWristTrackerGizmoZAxisColor = FColor(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
bDebugWristTrackerGizmoPersistentLines = false;
|
||||
DebugWristTrackerGizmoLifeTimeModifier = 1.1f;
|
||||
DebugWristTrackerGizmoDepthPriority = 0;
|
||||
DebugWristTrackerGizmoThickness = 1.0f;
|
||||
|
||||
bBackendInitialized = false;
|
||||
Glove = nullptr;
|
||||
WristLocation = FVector::ZeroVector;
|
||||
WristRotation = FRotator::ZeroRotator;
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetRight(const bool bRight)
|
||||
{
|
||||
SetTrackingSource(bRight ? EControllerHand::Right : EControllerHand::Left);
|
||||
}
|
||||
|
||||
ESGPositionalTrackingHardware USGWristTrackerComponent::GetTrackingHardware() const
|
||||
{
|
||||
if (OverridesPluginWristTrackingSettings())
|
||||
{
|
||||
return TrackingHardware;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetTrackingHardware();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetTrackingHardware(const ESGPositionalTrackingHardware InTrackingHardware)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingSettings(),
|
||||
TEXT( "Setting TrackingHardware is only permitted when bOverridePluginWristTrackingSettings is enabled!"));
|
||||
|
||||
TrackingHardware = InTrackingHardware;
|
||||
}
|
||||
|
||||
const FVector& USGWristTrackerComponent::GetTrackingHardwareLocationOffset() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetTrackingHardware() == ESGPositionalTrackingHardware::Custom,
|
||||
TEXT( "Getting TrackingHardwareLocationOffset is only permitted when TrackingHardware is set to Custom!"));
|
||||
|
||||
if (OverridesPluginWristTrackingSettings())
|
||||
{
|
||||
return TrackingHardwareLocationOffset;
|
||||
}
|
||||
|
||||
return IsRight()
|
||||
? USGSettings::GetInstance()->GetTrackingHardwareLocationOffsetRightHand()
|
||||
: USGSettings::GetInstance()->GetTrackingHardwareLocationOffsetLeftHand();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetTrackingHardwareLocationOffset(const FVector& InTrackingHardwareLocationOffset)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingSettings(),
|
||||
TEXT(
|
||||
"Setting TrackingHardwareLocationOffset is only permitted when bOverridePluginWristTrackingSettings is enabled!"
|
||||
));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetTrackingHardware() == ESGPositionalTrackingHardware::Custom,
|
||||
TEXT( "Setting TrackingHardwareLocationOffset is only permitted when TrackingHardware is set to Custom!"));
|
||||
|
||||
TrackingHardwareLocationOffset = InTrackingHardwareLocationOffset;
|
||||
}
|
||||
|
||||
const FRotator& USGWristTrackerComponent::GetTrackingHardwareRotationOffset() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetTrackingHardware() == ESGPositionalTrackingHardware::Custom,
|
||||
TEXT( "Getting TrackingHardwareRotationOffset is only permitted when TrackingHardware is set to Custom!"));
|
||||
|
||||
if (OverridesPluginWristTrackingSettings())
|
||||
{
|
||||
return TrackingHardwareRotationOffset;
|
||||
}
|
||||
|
||||
return IsRight()
|
||||
? USGSettings::GetInstance()->GetTrackingHardwareRotationOffsetRightHand()
|
||||
: USGSettings::GetInstance()->GetTrackingHardwareRotationOffsetLeftHand();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetTrackingHardwareRotationOffset(const FRotator& InTrackingHardwareRotationOffset)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingSettings(),
|
||||
TEXT(
|
||||
"Setting TrackingHardwareRotationOffset is only permitted when bOverridePluginWristTrackingSettings is enabled!"
|
||||
));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetTrackingHardware() == ESGPositionalTrackingHardware::Custom,
|
||||
TEXT("Setting TrackingHardwareRotationOffsetRightHand is only permitted when TrackingHardware is set to Custom!"
|
||||
));
|
||||
|
||||
TrackingHardwareRotationOffset = InTrackingHardwareRotationOffset;
|
||||
}
|
||||
|
||||
bool USGWristTrackerComponent::GetDrawDebugWristTrackerGizmo() const
|
||||
{
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return !!bDrawDebugWristTrackerGizmo;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDrawDebugWristTrackerGizmo();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDrawDebugWristTrackerGizmo(const bool bInDrawDebugWristTrackerGizmo)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT( "Setting bDrawDebugWristTrackerGizmo is only permitted when bOverridePluginWristTrackingDebugSettings is"
|
||||
" enabled!"));
|
||||
|
||||
bDrawDebugWristTrackerGizmo = bInDrawDebugWristTrackerGizmo;
|
||||
}
|
||||
|
||||
float USGWristTrackerComponent::GetDebugWristTrackerGizmoLength() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoLength is only permitted when bDrawDebugWristTrackerGizmo is enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoLength;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoLength();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoLength(const float InDebugWristTrackerGizmoLength)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoLength is only permitted when bOverridePluginWristTrackingDebugSettings is"
|
||||
" enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoLength is only permitted when bDrawDebugWristTrackerGizmo is enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoLength = InDebugWristTrackerGizmoLength;
|
||||
}
|
||||
|
||||
const FColor& USGWristTrackerComponent::GetDebugWristTrackerGizmoXAxisColor() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoXAxisColor is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoXAxisColor;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoXAxisColor();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoXAxisColor(
|
||||
const FColor& InDebugWristTrackerGizmoXAxisColor)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoXAxisColor is only permitted when bOverridePluginWristTrackingDebugSettings"
|
||||
" is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoXAxisColor is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoXAxisColor = InDebugWristTrackerGizmoXAxisColor;
|
||||
}
|
||||
|
||||
const FColor& USGWristTrackerComponent::GetDebugWristTrackerGizmoYAxisColor() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoYAxisColor is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoYAxisColor;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoYAxisColor();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoYAxisColor(
|
||||
const FColor& InDebugWristTrackerGizmoYAxisColor)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoYAxisColor is only permitted when bOverridePluginWristTrackingDebugSettings"
|
||||
" is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoYAxisColor is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoYAxisColor = InDebugWristTrackerGizmoYAxisColor;
|
||||
}
|
||||
|
||||
const FColor& USGWristTrackerComponent::GetDebugWristTrackerGizmoZAxisColor() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoZAxisColor is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoZAxisColor;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoZAxisColor();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoZAxisColor(
|
||||
const FColor& InDebugWristTrackerGizmoZAxisColor)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoZAxisColor is only permitted when bOverridePluginWristTrackingDebugSettings"
|
||||
" is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoZAxisColor is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoZAxisColor = InDebugWristTrackerGizmoZAxisColor;
|
||||
}
|
||||
|
||||
bool USGWristTrackerComponent::GetDebugWristTrackerGizmoPersistentLines() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting bDebugWristTrackerGizmoPersistentLines is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return !!bDebugWristTrackerGizmoPersistentLines;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoPersistentLines();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoPersistentLines(
|
||||
const bool bInDebugWristTrackerGizmoPersistentLines)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoPersistentLines is only permitted when"
|
||||
" bOverridePluginWristTrackingDebugSettings is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting bDebugWristTrackerGizmoPersistentLines is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
bDebugWristTrackerGizmoPersistentLines = bInDebugWristTrackerGizmoPersistentLines;
|
||||
}
|
||||
|
||||
float USGWristTrackerComponent::GetDebugWristTrackerGizmoLifeTimeModifier() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoLifeTimeModifier is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoLifeTimeModifier;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoLifeTimeModifier();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoLifeTimeModifier(
|
||||
const float InDebugWristTrackerGizmoLifeTimeModifier)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoLifetimeModifier is only permitted when"
|
||||
" bOverridePluginWristTrackingDebugSettings is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoLifeTimeModifier is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoLifeTimeModifier = InDebugWristTrackerGizmoLifeTimeModifier;
|
||||
}
|
||||
|
||||
uint8 USGWristTrackerComponent::GetDebugWristTrackerGizmoDepthPriority() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoDepthPriority is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoDepthPriority;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoDepthPriority();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoDepthPriority(const uint8 InDebugWristTrackerGizmoDepthPriority)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoDepthPriority is only permitted when"
|
||||
" bOverridePluginWristTrackingDebugSettings is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoDepthPriority is only permitted when bDrawDebugWristTrackerGizmo is"
|
||||
" enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoDepthPriority = InDebugWristTrackerGizmoDepthPriority;
|
||||
}
|
||||
|
||||
float USGWristTrackerComponent::GetDebugWristTrackerGizmoThickness() const
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Getting DebugWristTrackerGizmoThickness is only permitted when bDrawDebugWristTrackerGizmo is enabled!"));
|
||||
|
||||
if (OverridesPluginWristTrackingDebugSettings())
|
||||
{
|
||||
return DebugWristTrackerGizmoThickness;
|
||||
}
|
||||
|
||||
return USGSettings::GetInstance()->GetDebugWristTrackerGizmoThickness();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::SetDebugWristTrackerGizmoThickness(float InDebugWristTrackerGizmoThickness)
|
||||
{
|
||||
ensureAlwaysMsgf(
|
||||
OverridesPluginWristTrackingDebugSettings(),
|
||||
TEXT("Setting DebugWristTrackerGizmoDepthThickness is only permitted when"
|
||||
" bOverridePluginWristTrackingDebugSettings is enabled!"));
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
GetDrawDebugWristTrackerGizmo(),
|
||||
TEXT("Setting DebugWristTrackerGizmoThickness is only permitted when bDrawDebugWristTrackerGizmo is enabled!"));
|
||||
|
||||
DebugWristTrackerGizmoThickness = InDebugWristTrackerGizmoThickness;
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void USGWristTrackerComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
const FName PropertyName{
|
||||
PropertyChangedEvent.Property
|
||||
? PropertyChangedEvent.Property->GetFName()
|
||||
: NAME_None
|
||||
};
|
||||
|
||||
(void) PropertyName;
|
||||
}
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
void USGWristTrackerComponent::InitializeComponent()
|
||||
{
|
||||
Super::InitializeComponent();
|
||||
|
||||
if (Pimpl->InitializeBackend())
|
||||
{
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::UninitializeComponent()
|
||||
{
|
||||
Super::UninitializeComponent();
|
||||
|
||||
(void) Pimpl->UninitializeBackend();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (Pimpl->InitializeBackend())
|
||||
{
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
Super::EndPlay(EndPlayReason);
|
||||
|
||||
(void) Pimpl->UninitializeBackend();
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::TickComponent(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (Pimpl->IsEditor())
|
||||
{
|
||||
EditorTick(DeltaTime, TickType, ThisTickFunction);
|
||||
return;
|
||||
}
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (GetDrawDebugWristTrackerGizmo())
|
||||
{
|
||||
Pimpl->DrawDebugGizmo();
|
||||
}
|
||||
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
|
||||
void USGWristTrackerComponent::EditorTick(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
(void) Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
USGWristTrackerComponent::FImpl::FImpl(USGWristTrackerComponent* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
USGWristTrackerComponent::FImpl::~FImpl() = default;
|
||||
|
||||
bool USGWristTrackerComponent::FImpl::IsEditor() const
|
||||
{
|
||||
const UWorld* World{Owner->GetWorld()};
|
||||
if (World && (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::EditorPreview))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USGWristTrackerComponent::FImpl::InitializeBackend() const
|
||||
{
|
||||
if (!Owner->bBackendInitialized)
|
||||
{
|
||||
#if PLATFORM_ANDROID
|
||||
const int32_t Result = FSGConnect::Init();
|
||||
switch (Result)
|
||||
{
|
||||
case -3:
|
||||
SGLOG_ERROR("An Unexpected error occurred. Please try again.");
|
||||
return false;
|
||||
case -2:
|
||||
SGLOG_ERROR("Device Scanning is already running within a different program.");
|
||||
return false;
|
||||
case -1:
|
||||
SGLOG_ERROR("Device Scanning already being initialized (function called twice in short succession).");
|
||||
return false;
|
||||
case 0:
|
||||
// Do not pollute the logs!
|
||||
//SGLOG_ERROR("Device Scanning is already running within this program.");
|
||||
// We must return here in case there are two virtual hand components are present in the scene.
|
||||
return true;
|
||||
case 1:
|
||||
SGLOG("Successfully started up DeviceScanning from the current program.");
|
||||
break;
|
||||
default:
|
||||
ensureAlwaysMsgf(false, TEXT("Unhandled Init return status code!"));
|
||||
return false;
|
||||
}
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
// Ensure that the device list is empty before doing anything.
|
||||
FSGDeviceList::Dispose();
|
||||
FSGDeviceList::Reinitialize();
|
||||
|
||||
// Load the latest hand profiles.
|
||||
FSGHapticGloveHandProfiles::TryLoadingFromDisk();
|
||||
|
||||
Owner->bBackendInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USGWristTrackerComponent::FImpl::UninitializeBackend() const
|
||||
{
|
||||
// NOTE
|
||||
// In Editor builds we should be avoiding dispose, since stopping the game in PIE mode, causes the virtual-hand
|
||||
// to disappear in the editor as the plugin won't be able to retrieve the glove status anymore.
|
||||
#if ! WITH_EDITOR
|
||||
if (Owner->bBackendInitialized)
|
||||
{
|
||||
FSGDeviceList::Dispose();
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
const int32_t Result = FSGConnect::Dispose();
|
||||
switch (Result)
|
||||
{
|
||||
case -3:
|
||||
SGLOG_ERROR("An Unexpected error occurred. Please try again.");
|
||||
return false;
|
||||
case -2:
|
||||
SGLOG_ERROR("Not allowed to dispose of Device Scanning because this is not the program which started it.");
|
||||
return false;
|
||||
case -1:
|
||||
SGLOG_ERROR("Device Scanning is currently being disposed off. This takes a second or two. (function called twice in short succession).");
|
||||
return false;
|
||||
case 0:
|
||||
SGLOG_ERROR("There is no deviceScanner running from any program, so disposing is skipped.");
|
||||
return false;
|
||||
case 1:
|
||||
SGLOG("Successfully disposed of DeviceScanner resources.");
|
||||
break;
|
||||
default:
|
||||
ensureAlwaysMsgf(false, TEXT("Unhandled Dispose return status code!"));
|
||||
return false;
|
||||
}
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
Owner->bBackendInitialized = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* ! WITH_EDITOR */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USGWristTrackerComponent::FImpl::CheckGlove() const
|
||||
{
|
||||
if (!Owner->bBackendInitialized)
|
||||
{
|
||||
const bool bSucceeded = InitializeBackend();
|
||||
if (!bSucceeded)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool bGloveWasPresent = IsValid(Owner->Glove);
|
||||
const bool bFoundGlove = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
|
||||
|
||||
if (!bFoundGlove && bGloveWasPresent)
|
||||
{
|
||||
SGLOG_ERROR(FString::Printf(TEXT("Could not find a %s glove!"),
|
||||
(Owner->IsRight() ? TEXT("right-handed") : TEXT("left-handed"))));
|
||||
}
|
||||
|
||||
if (bFoundGlove)
|
||||
{
|
||||
UpdateWristTrackingData();
|
||||
}
|
||||
|
||||
return bFoundGlove;
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
|
||||
{
|
||||
ensureAlwaysMsgf(Owner->Glove, TEXT("Invalid Glove!"));
|
||||
|
||||
FVector TrackerLocation{Owner->GetRelativeLocation()};
|
||||
FRotator TrackerRotation{Owner->GetRelativeRotation()};
|
||||
|
||||
ESGPositionalTrackingHardware TrackerHardware = Owner->GetTrackingHardware();
|
||||
if (TrackerHardware == ESGPositionalTrackingHardware::None)
|
||||
{
|
||||
TrackerHardware = ESGPositionalTrackingHardware::Custom;
|
||||
}
|
||||
else if (TrackerHardware == ESGPositionalTrackingHardware::Custom)
|
||||
{
|
||||
TrackerLocation += Owner->GetTrackingHardwareLocationOffset();
|
||||
TrackerRotation += Owner->GetTrackingHardwareRotationOffset();
|
||||
}
|
||||
|
||||
FVector NewWristLocation;
|
||||
FRotator NewWristRotation;
|
||||
Owner->Glove->GetWristLocation(TrackerLocation, TrackerRotation, TrackerHardware,
|
||||
NewWristLocation, NewWristRotation);
|
||||
|
||||
const bool bLocationUpdated = !Owner->WristLocation.Equals(NewWristLocation, SMALL_NUMBER);
|
||||
const bool bRotationUpdated = !Owner->WristRotation.Equals(NewWristRotation, SMALL_NUMBER);
|
||||
|
||||
if (bLocationUpdated)
|
||||
{
|
||||
Owner->WristLocation = MoveTemp(NewWristLocation);
|
||||
}
|
||||
|
||||
if (bRotationUpdated)
|
||||
{
|
||||
Owner->WristRotation = MoveTemp(NewWristRotation);
|
||||
}
|
||||
|
||||
if (bLocationUpdated && Owner->WristLocationChangedEvent.IsBound())
|
||||
{
|
||||
Owner->WristLocationChangedEvent.Broadcast(Owner->WristLocation);
|
||||
}
|
||||
|
||||
if (bRotationUpdated && Owner->WristRotationChangedEvent.IsBound())
|
||||
{
|
||||
Owner->WristRotationChangedEvent.Broadcast(Owner->WristRotation);
|
||||
}
|
||||
|
||||
if ((bLocationUpdated && bRotationUpdated) && Owner->WristLocationAndRotationChangedEvent.IsBound())
|
||||
{
|
||||
Owner->WristLocationAndRotationChangedEvent.Broadcast(Owner->WristLocation, Owner->WristRotation);
|
||||
}
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::FImpl::DrawDebugGizmo()
|
||||
{
|
||||
const UWorld* World{Owner->GetWorld()};
|
||||
const FVector& Location{Owner->GetRelativeLocation()};
|
||||
const FRotator& Rotation{Owner->GetRelativeRotation()};
|
||||
const float Length = Owner->GetDebugWristTrackerGizmoLength();
|
||||
const bool bPersistentLines = Owner->GetDebugWristTrackerGizmoPersistentLines();
|
||||
const float LifeTime = UGameplayStatics::GetWorldDeltaSeconds(World)
|
||||
* Owner->GetDebugWristTrackerGizmoLifeTimeModifier();
|
||||
const float DepthPriority = Owner->GetDebugWristTrackerGizmoDepthPriority();
|
||||
const float Thickness = Owner->GetDebugWristTrackerGizmoThickness();
|
||||
const FColor& XAxisColor{Owner->GetDebugWristTrackerGizmoXAxisColor()};
|
||||
const FColor& YAxisColor{Owner->GetDebugWristTrackerGizmoYAxisColor()};
|
||||
const FColor& ZAxisColor{Owner->GetDebugWristTrackerGizmoZAxisColor()};
|
||||
|
||||
const FVector XAxisLineEnd(Location + Rotation.RotateVector(FVector(Length, 0.0f, 0.0f)));
|
||||
DrawDebugLine(World, Location, XAxisLineEnd, XAxisColor, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
|
||||
const FVector YAxisLineEnd(Location + Rotation.RotateVector(FVector{0.0f, Length, 0.0f}));
|
||||
DrawDebugLine(World, Location, YAxisLineEnd, YAxisColor, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
|
||||
const FVector ZAxisLineEnd{Location + Rotation.RotateVector(FVector{0.0f, 0.0f, Length})};
|
||||
DrawDebugLine(World, Location, ZAxisLineEnd, ZAxisColor, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/GameFramework//SGGameModeBase.h"
|
||||
|
||||
#include "SenseGlove/GameFramework/SGPawn.h"
|
||||
#include "SenseGlove/GameFramework/SGPlayerController.h"
|
||||
|
||||
ASGGameModeBase::ASGGameModeBase(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
DefaultPawnClass = ASGPawn::StaticClass();
|
||||
PlayerControllerClass = ASGPlayerController::StaticClass();
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/GameFramework/SGPawn.h"
|
||||
|
||||
#include "Camera/CameraComponent.h"
|
||||
|
||||
#include "SenseGlove/Components/SGVirtualHandComponent.h"
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
|
||||
struct ASGPawn::FImpl
|
||||
{
|
||||
/************************
|
||||
* Static methods
|
||||
************************/
|
||||
|
||||
/************************
|
||||
* Owner object
|
||||
************************/
|
||||
|
||||
ASGPawn* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(ASGPawn* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
};
|
||||
|
||||
ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
SceneRoot = ObjectInitializer.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneRoot"));
|
||||
SetRootComponent(SceneRoot);
|
||||
|
||||
Camera = ObjectInitializer.CreateDefaultSubobject<UCameraComponent>(this, TEXT("Camera"));
|
||||
Camera->SetupAttachment(GetRootComponent());
|
||||
Camera->SetCanEverAffectNavigation(false);
|
||||
|
||||
WristTrackerLeft = ObjectInitializer.CreateDefaultSubobject<USGWristTrackerComponent>(
|
||||
this, TEXT("WristTrackerLeft"));
|
||||
WristTrackerLeft->SetupAttachment(GetRootComponent());
|
||||
WristTrackerLeft->SetRight(false);
|
||||
|
||||
HandLeft = ObjectInitializer.CreateDefaultSubobject<USGVirtualHandComponent>(this, TEXT("HandLeft"));
|
||||
HandLeft->SetupAttachment(GetRootComponent());
|
||||
HandLeft->SetRight(false);
|
||||
HandLeft->SetHiddenIfNoGloveDetected(true);
|
||||
HandLeft->SetRelativeRotation(FRotator{0.0f, -90.0f, 0.0f},
|
||||
false, nullptr, ETeleportType::None);
|
||||
HandLeft->SetRelativeLocation(FVector{30.0f, -20.0f, -10.0f},
|
||||
false, nullptr, ETeleportType::None);
|
||||
|
||||
WristTrackerRight = ObjectInitializer.CreateDefaultSubobject<USGWristTrackerComponent>(
|
||||
this, TEXT("WristTrackerRight"));
|
||||
WristTrackerRight->SetupAttachment(GetRootComponent());
|
||||
WristTrackerRight->SetRight(true);
|
||||
|
||||
HandRight = ObjectInitializer.CreateDefaultSubobject<USGVirtualHandComponent>(this, TEXT("HandRight"));
|
||||
HandRight->SetupAttachment(GetRootComponent());
|
||||
HandRight->SetRight(true);
|
||||
HandRight->SetHiddenIfNoGloveDetected(true);
|
||||
HandRight->SetRelativeRotation(FRotator{0.0f, -90.0f, 0.0f},
|
||||
false, nullptr, ETeleportType::None);
|
||||
HandRight->SetRelativeLocation(FVector{30.0f, 20.0f, -10.0f},
|
||||
false, nullptr, ETeleportType::None);
|
||||
}
|
||||
|
||||
void ASGPawn::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
WristTrackerLeft->IsLeft() && HandLeft->IsLeft(),
|
||||
TEXT("The left hand and the left wrist do not track the left hand!"));
|
||||
ensureAlwaysMsgf(
|
||||
WristTrackerRight->IsRight() && HandRight->IsRight(),
|
||||
TEXT("The right hand and the right wrist do not track the right hand!"));
|
||||
|
||||
WristTrackerLeft->OnWristLocationChanged().AddWeakLambda(this, [&](const FVector& Location)-> void
|
||||
{
|
||||
HandLeft->SetRelativeLocation(Location);
|
||||
});
|
||||
|
||||
WristTrackerLeft->OnWristRotationChanged().AddWeakLambda(this, [&](const FRotator& Rotation)-> void
|
||||
{
|
||||
HandLeft->SetRelativeRotation(Rotation);
|
||||
});
|
||||
|
||||
WristTrackerRight->OnWristLocationChanged().AddWeakLambda(this, [&](const FVector& Location)-> void
|
||||
{
|
||||
HandRight->SetRelativeLocation(Location);
|
||||
});
|
||||
|
||||
WristTrackerRight->OnWristRotationChanged().AddWeakLambda(this, [&](const FRotator& Rotation)-> void
|
||||
{
|
||||
HandRight->SetRelativeRotation(Rotation);
|
||||
});
|
||||
}
|
||||
|
||||
void ASGPawn::PreInitializeComponents()
|
||||
{
|
||||
Super::PreInitializeComponents();
|
||||
|
||||
WristTrackerLeft->SetRight(HandLeft->IsRight());
|
||||
WristTrackerRight->SetRight(HandRight->IsRight());
|
||||
}
|
||||
|
||||
ASGPawn::FImpl::FImpl(ASGPawn* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
ASGPawn::FImpl::~FImpl() = default;
|
||||
|
||||
void ASGPawn::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/GameFramework/SGPlayerController.h"
|
||||
|
||||
ASGPlayerController::ASGPlayerController(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void ASGPlayerController::SetupInputComponent()
|
||||
{
|
||||
Super::SetupInputComponent();
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/GameFramework/SGVirtualHandActor.h"
|
||||
|
||||
#include "SenseGlove/Components/SGVirtualHandComponent.h"
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
|
||||
struct ASGVirtualHandActor::FImpl
|
||||
{
|
||||
/************************
|
||||
* Owner object
|
||||
************************/
|
||||
|
||||
ASGVirtualHandActor* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(ASGVirtualHandActor* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
};
|
||||
|
||||
ASGVirtualHandActor::ASGVirtualHandActor(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
|
||||
SetRootComponent(SceneRoot);
|
||||
|
||||
VirtualHand = CreateDefaultSubobject<USGVirtualHandComponent>(TEXT("VirtualHand"));
|
||||
VirtualHand->SetupAttachment(RootComponent);
|
||||
VirtualHand->SetRelativeRotation(FRotator{0.0f, -90.0f, 0.0f},
|
||||
false, nullptr, ETeleportType::None);
|
||||
|
||||
WristTracker = CreateDefaultSubobject<USGWristTrackerComponent>(TEXT("WristTracker"));
|
||||
WristTracker->SetupAttachment(RootComponent);
|
||||
|
||||
WristTracker->SetRight(VirtualHand->IsRight());
|
||||
}
|
||||
|
||||
void ASGVirtualHandActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
ensureAlwaysMsgf(
|
||||
(WristTracker->IsLeft() && VirtualHand->IsLeft())
|
||||
|| (WristTracker->IsRight() && VirtualHand->IsRight()),
|
||||
TEXT("The virtual hand component and the wrist tracker component do not track the same hand!"));
|
||||
|
||||
WristTracker->OnWristLocationChanged().AddWeakLambda(this, [&](const FVector& Location)-> void
|
||||
{
|
||||
VirtualHand->SetRelativeLocation(Location);
|
||||
});
|
||||
|
||||
WristTracker->OnWristRotationChanged().AddWeakLambda(this, [&](const FRotator& Rotation)-> void
|
||||
{
|
||||
VirtualHand->SetRelativeRotation(Rotation);
|
||||
});
|
||||
}
|
||||
|
||||
void ASGVirtualHandActor::PreInitializeComponents()
|
||||
{
|
||||
Super::PreInitializeComponents();
|
||||
|
||||
WristTracker->SetRight(VirtualHand->IsRight());
|
||||
}
|
||||
|
||||
bool ASGVirtualHandActor::IsLeft() const
|
||||
{
|
||||
return WristTracker->IsLeft() && VirtualHand->IsLeft();
|
||||
}
|
||||
|
||||
bool ASGVirtualHandActor::IsRight() const
|
||||
{
|
||||
return WristTracker->IsRight() && VirtualHand->IsRight();
|
||||
}
|
||||
|
||||
void ASGVirtualHandActor::SetRight(const bool bRight)
|
||||
{
|
||||
WristTracker->SetRight(bRight);
|
||||
VirtualHand->SetRight(bRight);
|
||||
}
|
||||
|
||||
bool ASGVirtualHandActor::IsGloveConnected() const
|
||||
{
|
||||
return VirtualHand->IsGloveConnected();
|
||||
}
|
||||
|
||||
ASGVirtualHandActor::FImpl::FImpl(ASGVirtualHandActor* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
ASGVirtualHandActor::FImpl::~FImpl() = default;
|
||||
|
||||
void ASGVirtualHandActor::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Animation/AnimInstance.h"
|
||||
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h"
|
||||
|
||||
#include "SGVirtualHandAnimInstance.generated.h"
|
||||
|
||||
UCLASS(Transient, Blueprintable, BlueprintType, meta=(BlueprintThreadSafe), Within=SkeletalMeshComponent)
|
||||
class SENSEGLOVE_API USGVirtualHandAnimInstance : public UAnimInstance
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
protected:
|
||||
virtual FSGVirtualHandAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
|
||||
#include "SGVirtualHandAnimInstanceProxy.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct SENSEGLOVE_API FSGVirtualHandAnimInstanceProxy : public FAnimInstanceProxy
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
TMap<FName, FRotator> BonesRotations;
|
||||
|
||||
public:
|
||||
FSGVirtualHandAnimInstanceProxy();
|
||||
FSGVirtualHandAnimInstanceProxy(UAnimInstance* Instance);
|
||||
|
||||
protected:
|
||||
virtual void PreEvaluateAnimation(UAnimInstance* InAnimInstance) override;
|
||||
|
||||
virtual bool Evaluate(FPoseContext& Output) override;
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Math/Rotator.h"
|
||||
#include "Math/Transform.h"
|
||||
#include "ReferenceSkeleton.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
|
||||
#include "SGVirtualHandComponent.generated.h"
|
||||
|
||||
class USkeletalMesh;
|
||||
|
||||
class USGHandPose;
|
||||
class USGHapticGlove;
|
||||
|
||||
UCLASS(Config=Engine, Blueprintable, ClassGroup=(Rendering, Common), hidecategories=(Object, "Mesh|SkeletalAsset"),
|
||||
editinlinenew, meta=(BlueprintSpawnableComponent))
|
||||
class SENSEGLOVE_API USGVirtualHandComponent : public USkeletalMeshComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
static const TArray<TArray<FName>>& GetLeftHandFingerBoneNames();
|
||||
static const TArray<TArray<FName>>& GetRightHandFingerBoneNames();
|
||||
|
||||
static const FName& GetLeftHandFingerBoneName(int32 Finger, int32 Joint);
|
||||
static const FName& GetRightHandFingerBoneName(int32 Finger, int32 Joint);
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
uint8 bRight : 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
uint8 bHiddenInGameIfNoGloveDetected : 1;
|
||||
|
||||
private:
|
||||
UPROPERTY(Transient)
|
||||
uint8 bBackendInitialized : 1;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
USGHapticGlove* Glove;
|
||||
|
||||
public:
|
||||
FORCEINLINE bool IsLeft() const
|
||||
{
|
||||
return !IsRight();
|
||||
}
|
||||
|
||||
FORCEINLINE bool IsRight() const
|
||||
{
|
||||
return !!bRight;
|
||||
}
|
||||
|
||||
void SetRight(const bool bInRight);
|
||||
|
||||
FORCEINLINE bool IsHiddenInGameIfNoGloveDetected() const
|
||||
{
|
||||
return !!bHiddenInGameIfNoGloveDetected;
|
||||
}
|
||||
|
||||
FORCEINLINE void SetHiddenIfNoGloveDetected(const bool bInHiddenIfNoGloveDetected)
|
||||
{
|
||||
bHiddenInGameIfNoGloveDetected = bInHiddenIfNoGloveDetected;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void SetAnimClass(class UClass* NewClass) override;
|
||||
|
||||
virtual void PostInitProperties() override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void UninitializeComponent() override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
virtual void TickComponent(float DeltaTime,
|
||||
enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
virtual void SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose = true) override;
|
||||
|
||||
protected:
|
||||
virtual void EditorTick(float DeltaTime,
|
||||
enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction);
|
||||
|
||||
public:
|
||||
bool IsGloveConnected() const;
|
||||
USGHandPose* GetHandPose();
|
||||
|
||||
public:
|
||||
const FName& GetFingerBoneName(int32 Finger, int32 Joint) const;
|
||||
const FTransform& GetFingerBoneRefTransform(int32 Finger, int32 Joint) const;
|
||||
|
||||
FRotator GetFingerBoneRefRotation(int32 Finger, int32 Joint) const;
|
||||
TMap<FName, FRotator> GetFingersBonesRotations();
|
||||
};
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Math/Rotator.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "MotionControllerComponent.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
|
||||
#include "SGTypes/SGCoreTypes.h"
|
||||
|
||||
#include "SGWristTrackerComponent.generated.h"
|
||||
|
||||
class USGHandPose;
|
||||
class USGHapticGlove;
|
||||
|
||||
UCLASS(Blueprintable, ClassGroup = MotionController, meta = (BlueprintSpawnableComponent))
|
||||
class SENSEGLOVE_API USGWristTrackerComponent : public UMotionControllerComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
DECLARE_EVENT_OneParam(USGWristTrackerComponent, FWristLocationChangedEvent, const FVector&)
|
||||
|
||||
FWristLocationChangedEvent& OnWristLocationChanged()
|
||||
{
|
||||
return WristLocationChangedEvent;
|
||||
};
|
||||
|
||||
DECLARE_EVENT_OneParam(USGWristTrackerComponent, FWristRotationChangedEvent, const FRotator&)
|
||||
|
||||
FWristRotationChangedEvent& OnWristRotationChanged()
|
||||
{
|
||||
return WristRotationChangedEvent;
|
||||
};
|
||||
|
||||
DECLARE_EVENT_TwoParams(USGWristTrackerComponent, FWristLocationAndRotationChangedEvent,
|
||||
const FVector&, const FRotator&)
|
||||
|
||||
FWristLocationAndRotationChangedEvent& OnWristLocationAndRotationChanged()
|
||||
{
|
||||
return WristLocationAndRotationChangedEvent;
|
||||
};
|
||||
|
||||
private:
|
||||
FWristLocationChangedEvent WristLocationChangedEvent;
|
||||
FWristRotationChangedEvent WristRotationChangedEvent;
|
||||
FWristLocationAndRotationChangedEvent WristLocationAndRotationChangedEvent;
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
private:
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings")
|
||||
uint8 bOverridePluginWristTrackingSettings : 1;
|
||||
|
||||
/**
|
||||
* If set to Custom, any desired location and rotation can be specified.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingSettings", EditConditionHides))
|
||||
ESGPositionalTrackingHardware TrackingHardware;
|
||||
|
||||
/**
|
||||
* Valid only if TrackingHardware is set to Custom.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition=
|
||||
"bOverridePluginWristTrackingSettings && TrackingHardware == ESGPositionalTrackingHardware::Custom",
|
||||
EditConditionHides))
|
||||
FVector TrackingHardwareLocationOffset;
|
||||
|
||||
/**
|
||||
* Valid only if TrackingHardware is set to Custom.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition=
|
||||
"bOverridePluginWristTrackingSettings && TrackingHardware == ESGPositionalTrackingHardware::Custom",
|
||||
EditConditionHides))
|
||||
FRotator TrackingHardwareRotationOffset;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings")
|
||||
uint8 bOverridePluginWristTrackingDebugSettings : 1;
|
||||
|
||||
/**
|
||||
* If enabled, draws debug Wrist trackers where possible.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings", EditConditionHides))
|
||||
uint8 bDrawDebugWristTrackerGizmo : 1;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
float DebugWristTrackerGizmoLength;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
FColor DebugWristTrackerGizmoXAxisColor;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
FColor DebugWristTrackerGizmoYAxisColor;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
FColor DebugWristTrackerGizmoZAxisColor;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
uint8 bDebugWristTrackerGizmoPersistentLines : 1;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
float DebugWristTrackerGizmoLifeTimeModifier;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
uint8 DebugWristTrackerGizmoDepthPriority;
|
||||
|
||||
/**
|
||||
* Valid only if bDrawDebugWristTrackerGizmo is enabled.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "Override Plugin Settings",
|
||||
meta=(EditCondition="bOverridePluginWristTrackingDebugSettings && bDrawDebugWristTrackerGizmo",
|
||||
EditConditionHides))
|
||||
float DebugWristTrackerGizmoThickness;
|
||||
|
||||
private:
|
||||
UPROPERTY(Transient)
|
||||
uint8 bBackendInitialized : 1;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
USGHapticGlove* Glove;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FVector WristLocation;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FRotator WristRotation;
|
||||
|
||||
public:
|
||||
FORCEINLINE bool OverridesPluginWristTrackingSettings() const
|
||||
{
|
||||
return !!bOverridePluginWristTrackingSettings;
|
||||
}
|
||||
|
||||
FORCEINLINE void OverridePluginWristTrackingSettings(const bool bInOverridePluginWristTrackingSettings)
|
||||
{
|
||||
bOverridePluginWristTrackingSettings = bInOverridePluginWristTrackingSettings;
|
||||
}
|
||||
|
||||
ESGPositionalTrackingHardware GetTrackingHardware() const;
|
||||
void SetTrackingHardware(ESGPositionalTrackingHardware InTrackingHardware);
|
||||
|
||||
const FVector& GetTrackingHardwareLocationOffset() const;
|
||||
void SetTrackingHardwareLocationOffset(const FVector& InTrackingHardwareLocationOffset);
|
||||
|
||||
const FRotator& GetTrackingHardwareRotationOffset() const;
|
||||
void SetTrackingHardwareRotationOffset(const FRotator& InTrackingHardwareRotationOffset);
|
||||
|
||||
FORCEINLINE bool OverridesPluginWristTrackingDebugSettings() const
|
||||
{
|
||||
return !!bOverridePluginWristTrackingDebugSettings;
|
||||
}
|
||||
|
||||
FORCEINLINE void OverridePluginWristTrackingDebugSettings(const bool bInOverridePluginWristTrackingDebugSettings)
|
||||
{
|
||||
bOverridePluginWristTrackingDebugSettings = bInOverridePluginWristTrackingDebugSettings;
|
||||
}
|
||||
|
||||
bool GetDrawDebugWristTrackerGizmo() const;
|
||||
void SetDrawDebugWristTrackerGizmo(bool bInDrawDebugWristTrackerGizmo);
|
||||
|
||||
float GetDebugWristTrackerGizmoLength() const;
|
||||
void SetDebugWristTrackerGizmoLength(float InDebugWristTrackerGizmoLength);
|
||||
|
||||
const FColor& GetDebugWristTrackerGizmoXAxisColor() const;
|
||||
void SetDebugWristTrackerGizmoXAxisColor(const FColor& InDebugWristTrackerGizmoXAxisColor);
|
||||
|
||||
const FColor& GetDebugWristTrackerGizmoYAxisColor() const;
|
||||
void SetDebugWristTrackerGizmoYAxisColor(const FColor& InDebugWristTrackerGizmoYAxisColor);
|
||||
|
||||
const FColor& GetDebugWristTrackerGizmoZAxisColor() const;
|
||||
void SetDebugWristTrackerGizmoZAxisColor(const FColor& InDebugWristTrackerGizmoZAxisColor);
|
||||
|
||||
bool GetDebugWristTrackerGizmoPersistentLines() const;
|
||||
void SetDebugWristTrackerGizmoPersistentLines(bool bInDebugWristTrackerGizmoPersistentLines);
|
||||
|
||||
float GetDebugWristTrackerGizmoLifeTimeModifier() const;
|
||||
void SetDebugWristTrackerGizmoLifeTimeModifier(float InDebugWristTrackerGizmoLifeTimeModifier);
|
||||
|
||||
uint8 GetDebugWristTrackerGizmoDepthPriority() const;
|
||||
void SetDebugWristTrackerGizmoDepthPriority(uint8 InDebugWristTrackerGizmoDepthPriority);
|
||||
|
||||
float GetDebugWristTrackerGizmoThickness() const;
|
||||
void SetDebugWristTrackerGizmoThickness(float InDebugWristTrackerGizmoThickness);
|
||||
|
||||
FORCEINLINE bool IsLeft() const
|
||||
{
|
||||
return GetTrackingSource() == EControllerHand::Left;
|
||||
}
|
||||
|
||||
FORCEINLINE bool IsRight() const
|
||||
{
|
||||
return GetTrackingSource() == EControllerHand::Right;
|
||||
}
|
||||
|
||||
void SetRight(const bool bRight);
|
||||
|
||||
FORCEINLINE const FVector& GetWristLocation() const
|
||||
{
|
||||
return WristLocation;
|
||||
}
|
||||
|
||||
FORCEINLINE const FRotator& GetWristRotation() const
|
||||
{
|
||||
return WristRotation;
|
||||
}
|
||||
|
||||
public:
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void UninitializeComponent() override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
virtual void TickComponent(float DeltaTime,
|
||||
enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
protected:
|
||||
virtual void EditorTick(float DeltaTime,
|
||||
enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction);
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
|
||||
#include "SGGameModeBase.generated.h"
|
||||
|
||||
UCLASS(Config=Game, NotPlaceable, BlueprintType, Blueprintable, Transient)
|
||||
class SENSEGLOVE_API ASGGameModeBase : public AGameModeBase
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
|
||||
#include "SGPawn.generated.h"
|
||||
|
||||
class UCameraComponent;
|
||||
|
||||
class USGVirtualHandComponent;
|
||||
class USGWristTrackerComponent;
|
||||
|
||||
UCLASS(Config=Game, BlueprintType, Blueprintable)
|
||||
class SENSEGLOVE_API ASGPawn : public APawn
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USceneComponent* SceneRoot;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
UCameraComponent* Camera;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGWristTrackerComponent* WristTrackerLeft;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGWristTrackerComponent* WristTrackerRight;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGVirtualHandComponent* HandLeft;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGVirtualHandComponent* HandRight;
|
||||
|
||||
public:
|
||||
FORCEINLINE UCameraComponent* GetCamera() const
|
||||
{
|
||||
return Camera;
|
||||
}
|
||||
|
||||
FORCEINLINE USGWristTrackerComponent* GetWristTrackerLeft() const
|
||||
{
|
||||
return WristTrackerLeft;
|
||||
}
|
||||
|
||||
FORCEINLINE USGWristTrackerComponent* GetWristTrackerRight() const
|
||||
{
|
||||
return WristTrackerRight;
|
||||
}
|
||||
|
||||
FORCEINLINE USGVirtualHandComponent* GetHandLeft() const
|
||||
{
|
||||
return HandLeft;
|
||||
}
|
||||
|
||||
FORCEINLINE USGVirtualHandComponent* GetHandRight() const
|
||||
{
|
||||
return HandRight;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void PreInitializeComponents() override;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/PlayerController.h"
|
||||
|
||||
#include "SGPlayerController.generated.h"
|
||||
|
||||
UCLASS(Config=Game, BlueprintType, Blueprintable)
|
||||
class SENSEGLOVE_API ASGPlayerController : public APlayerController
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
protected:
|
||||
virtual void SetupInputComponent() override;
|
||||
};
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
|
||||
#include "SGVirtualHandActor.generated.h"
|
||||
|
||||
class USkeletalMesh;
|
||||
class USkeleton;
|
||||
class USceneComponent;
|
||||
|
||||
class USGHandPose;
|
||||
class USGVirtualHandComponent;
|
||||
class USGWristTrackerComponent;
|
||||
|
||||
UCLASS(Config=Game, BlueprintType)
|
||||
class SENSEGLOVE_API ASGVirtualHandActor : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USceneComponent* SceneRoot;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGWristTrackerComponent* WristTracker;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGVirtualHandComponent* VirtualHand;
|
||||
|
||||
public:
|
||||
FORCEINLINE USGWristTrackerComponent* GetWristTracker() const
|
||||
{
|
||||
return WristTracker;
|
||||
}
|
||||
|
||||
FORCEINLINE USGVirtualHandComponent* GetVirtualHand() const
|
||||
{
|
||||
return VirtualHand;
|
||||
}
|
||||
|
||||
protected:
|
||||
FORCEINLINE void SetMesh(USGVirtualHandComponent* InVirtualHand)
|
||||
{
|
||||
VirtualHand = InVirtualHand;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void PreInitializeComponents() override;
|
||||
|
||||
public:
|
||||
bool IsLeft() const;
|
||||
bool IsRight() const;
|
||||
void SetRight(bool bRight);
|
||||
|
||||
bool IsGloveConnected() const;
|
||||
};
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
@@ -52,11 +52,14 @@ public class SenseGlove : ModuleRules
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"AnimGraphRuntime",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"HeadMountedDisplay",
|
||||
"SenseGloveConnect",
|
||||
"SenseGloveCore",
|
||||
"SenseGloveLog",
|
||||
"SenseGloveSettings",
|
||||
"SenseGloveTypes",
|
||||
}
|
||||
);
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SGAndroid/SGConnectJNI.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include "Android/AndroidApplication.h"
|
||||
#include "Android/AndroidJava.h"
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include "SGConnectImpl/SGExportedFunctions.h"
|
||||
#include "SGInterop/SGIC_FString.h"
|
||||
#include "SGInterop/SGIC_jclass.h"
|
||||
#include "SGInterop/SGIC_jmethodID.h"
|
||||
#include "SGInterop/SGIC_JNIEnv_Ptr.h"
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
int32 FSGConnectJNI::Initialize()
|
||||
{
|
||||
int32 Result = -999999;
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
static constexpr char SGCONNECT_JAVA_CLASS_NAME[] = "com.senseglove.sgconnect.SGConnect";
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to get the Android JNI environment...");
|
||||
|
||||
JNIEnv* Env = FAndroidApplication::GetJavaEnv();
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!Env)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI environmnet!");
|
||||
return -1999999;
|
||||
}
|
||||
FSGIC_JNIEnv_Ptr InEnvContainer{Env};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android Java class...");
|
||||
|
||||
jclass Class = FAndroidApplication::FindJavaClass(SGCONNECT_JAVA_CLASS_NAME);
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (Env->IsSameObject(Class, nullptr))
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android Java class!");
|
||||
return -2999999;
|
||||
}
|
||||
Class = (jclass)Env->NewGlobalRef(Class);
|
||||
FSGIC_jclass InClassContainer{Class};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'Init'...");
|
||||
|
||||
jmethodID InitMethodID = Env->GetStaticMethodID(Class, "Init", "()I");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!InitMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'Init'!");
|
||||
return -3999999;
|
||||
}
|
||||
FSGIC_jmethodID InInitMethodIDContainer{InitMethodID};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'Dispose'...");
|
||||
|
||||
jmethodID DisposeMethodID = Env->GetStaticMethodID(Class, "Dispose", "()I");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!DisposeMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'Dispose'!");
|
||||
return -4999999;
|
||||
}
|
||||
FSGIC_jmethodID InDisposeMethodIDContainer{DisposeMethodID};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'GetLibraryVersion'...");
|
||||
|
||||
jmethodID GetLibraryVersionMethodID = Env->GetStaticMethodID(Class, "GetLibraryVersion", "()Ljava/lang/String;");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!GetLibraryVersionMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'GetLibraryVersion'!");
|
||||
return -5999999;
|
||||
}
|
||||
FSGIC_jmethodID InGetLibraryVersionMethodIDContainer{GetLibraryVersionMethodID};
|
||||
|
||||
FSGIC_FString ProjectSavedDirContainer{FPaths::ProjectSavedDir()};
|
||||
|
||||
Result = SGConnectImpl_Android_Initialize(&InEnvContainer, &InClassContainer,
|
||||
&InInitMethodIDContainer,
|
||||
&InDisposeMethodIDContainer,
|
||||
&InGetLibraryVersionMethodIDContainer,
|
||||
&ProjectSavedDirContainer);
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
return Result;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SGAndroid/SGCoreJNI.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include "Android/AndroidApplication.h"
|
||||
#include "Android/AndroidJava.h"
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include "SGCoreImpl/SGExportedFunctions.h"
|
||||
#include "SGInterop/SGIC_FString.h"
|
||||
#include "SGInterop/SGIC_jclass.h"
|
||||
#include "SGInterop/SGIC_jmethodID.h"
|
||||
#include "SGInterop/SGIC_JNIEnv_Ptr.h"
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
#include "SGLog/SGLog.h"
|
||||
|
||||
int32 FSGCoreJNI::Initialize()
|
||||
{
|
||||
int32 Result = -999999;
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
static constexpr char SGCONNECT_JAVA_CLASS_NAME[] = "com.senseglove.sgconnect.SGConnect";
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to get the Android JNI environment...");
|
||||
|
||||
JNIEnv* Env = FAndroidApplication::GetJavaEnv();
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!Env)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI environmnet!");
|
||||
return -1999999;
|
||||
}
|
||||
FSGIC_JNIEnv_Ptr InEnvContainer{Env};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android Java class...");
|
||||
|
||||
jclass Class = FAndroidApplication::FindJavaClass(SGCONNECT_JAVA_CLASS_NAME);
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (Env->IsSameObject(Class, nullptr))
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android Java class!");
|
||||
return -2999999;
|
||||
}
|
||||
Class = (jclass)Env->NewGlobalRef(Class);
|
||||
FSGIC_jclass InClassContainer{Class};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'ActiveDevices'...");
|
||||
|
||||
jmethodID ActiveDevicesMethodID = Env->GetStaticMethodID(Class, "ActiveDevices", "()I");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!ActiveDevicesMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'ActiveDevices'!");
|
||||
return -3999999;
|
||||
}
|
||||
FSGIC_jmethodID InActiveDevicesMethodIDContainer{ActiveDevicesMethodID};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'GetDeviceString'...");
|
||||
|
||||
jmethodID GetDeviceStringMethodID = Env->GetStaticMethodID(Class, "GetDeviceString", "(I)Ljava/lang/String;");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!GetDeviceStringMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'GetDeviceString'!");
|
||||
return -4999999;
|
||||
}
|
||||
FSGIC_jmethodID InGetDeviceStringMethodIDContainer{GetDeviceStringMethodID};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'GetSensorString'...");
|
||||
|
||||
jmethodID GetSensorStringMethodID = Env->GetStaticMethodID(Class, "GetSensorString", "(I)Ljava/lang/String;");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!GetSensorStringMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'GetSensorString'!");
|
||||
return -5999999;
|
||||
}
|
||||
FSGIC_jmethodID InGetSensorStringMethodIDContainer{GetSensorStringMethodID};
|
||||
|
||||
SGLOG("FSGCoreJNI: attempting to find the Android JNI method 'WriteHaptics'...");
|
||||
|
||||
jmethodID WriteHapticsMethodID = Env->GetStaticMethodID(Class, "WriteHaptics", "(ILjava/lang/String;)I");
|
||||
FAndroidApplication::CheckJavaException();
|
||||
if (!WriteHapticsMethodID)
|
||||
{
|
||||
SGLOG_ERROR("FSGCoreJNI: failed to get the Android JNI method 'WriteHaptics'!");
|
||||
return -6999999;
|
||||
}
|
||||
FSGIC_jmethodID InWriteHapticsMethodIDContainer{WriteHapticsMethodID};
|
||||
|
||||
FSGIC_FString ProjectSavedDirContainer{FPaths::ProjectSavedDir()};
|
||||
|
||||
Result = SGCoreImpl_Android_Initialize(&InEnvContainer, &InClassContainer,
|
||||
&InActiveDevicesMethodIDContainer,
|
||||
&InGetDeviceStringMethodIDContainer,
|
||||
&InGetSensorStringMethodIDContainer,
|
||||
&InWriteHapticsMethodIDContainer,
|
||||
&ProjectSavedDirContainer);
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
|
||||
return Result;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGloveAndroid.h"
|
||||
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "SenseGloveAndroidModule.h"
|
||||
|
||||
IMPLEMENT_MODULE(FSenseGloveAndroidModule, SenseGloveAndroid)
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGloveAndroidModule.h"
|
||||
|
||||
#include "SGAndroid/SGConnectJNI.h"
|
||||
#include "SGAndroid/SGCoreJNI.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FSenseGloveAndroidModule"
|
||||
|
||||
void FSenseGloveAndroidModule::StartupModule()
|
||||
{
|
||||
SGLOG("Starting up SenseGloveAndroid module...");
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
const int32 R1 = FSGConnectJNI::Initialize();
|
||||
const int32 R2 = FSGCoreJNI::Initialize();
|
||||
|
||||
ensureAlwaysMsgf(R1 == 0,
|
||||
TEXT("Failed to initialize the SGConnect JNI bridge to SGConnect for Android! Status Code: %d"), R1);
|
||||
|
||||
ensureAlwaysMsgf(R2 == 0,
|
||||
TEXT("Failed to initialize the SGCore JNI bridge to SGConnect for Android! Status Code: %d"), R2);
|
||||
#endif /* PLATFORM_ANDROID */
|
||||
}
|
||||
|
||||
void FSenseGloveAndroidModule::PreUnloadCallback()
|
||||
{
|
||||
SGLOG("Unloading SenseGloveAndroid module...");
|
||||
}
|
||||
|
||||
void FSenseGloveAndroidModule::PostLoadCallback()
|
||||
{
|
||||
SGLOG("Loading SenseGloveAndroid module has succeeded!");
|
||||
}
|
||||
|
||||
void FSenseGloveAndroidModule::ShutdownModule()
|
||||
{
|
||||
SGLOG("Shutting down SenseGloveAndroid module...");
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "SenseGloveAndroid"
|
||||
|
||||
class FSenseGloveAndroidModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void PreUnloadCallback() override;
|
||||
virtual void PostLoadCallback() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
+9
-28
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
@@ -35,34 +35,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "Misc/AssertionMacros.h"
|
||||
#include "Templates/UnrealTemplate.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "UObject/Package.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
|
||||
class SENSEGLOVEUTILS_API SGEnumUtils
|
||||
{
|
||||
public:
|
||||
template<typename E>
|
||||
static FORCEINLINE FString ValueToName(const FString& Enum, const E Value)
|
||||
{
|
||||
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Enum, true);
|
||||
if (!ensureAlwaysMsgf(EnumPtr, TEXT("No such enum exists!"))) {
|
||||
return FString("None");
|
||||
}
|
||||
return EnumPtr->GetNameByValue(StaticCast<int64>(Value)).ToString();
|
||||
}
|
||||
#include "SGConnectJNI.generated.h"
|
||||
|
||||
template <typename E>
|
||||
static FORCEINLINE E NameToValue(const FString& Enum, const FString& Name)
|
||||
{
|
||||
UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Enum, true);
|
||||
if (!ensureAlwaysMsgf(EnumPtr, TEXT("No such enum exists!"))) {
|
||||
return StaticCast<E>(0);
|
||||
}
|
||||
return StaticCast<E>(EnumPtr->GetValueByName(FName(*Name)));
|
||||
}
|
||||
USTRUCT()
|
||||
struct SENSEGLOVEANDROID_API FSGConnectJNI
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static int32 Initialize();
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UObject/ObjectMacros.h"
|
||||
|
||||
#include "SGCoreJNI.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct SENSEGLOVEANDROID_API FSGCoreJNI
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static int32 Initialize();
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class SenseGloveAndroid : ModuleRules
|
||||
{
|
||||
public SenseGloveAndroid(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"SenseGloveConnectImpl",
|
||||
"SenseGloveCoreImpl",
|
||||
"SenseGloveInterop",
|
||||
"SenseGloveLog",
|
||||
}
|
||||
);
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
AdditionalPropertiesForReceipt.Add("AndroidPlugin",
|
||||
Path.Combine(ModuleDirectory, "SenseGloveAndroid_UPL.xml"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
@author Mamadou Babaei <mamadou@senseglove.com>
|
||||
|
||||
@section LICENSE
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2020 - 2023 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.
|
||||
-->
|
||||
|
||||
<!-- https://docs.unrealengine.com/en-US/SharingAndReleasing/Mobile/UnrealPluginLanguage/index.html -->
|
||||
|
||||
<root xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<init>
|
||||
<log text="SenseGloveAndroid [INIT]: adding properties to the manifest and Gradle"/>
|
||||
<trace enable="true"/>
|
||||
|
||||
<setBool result="bSupportedArch" value="false"/>
|
||||
|
||||
<isArch arch="armeabi-v7a">
|
||||
<setBool result="bSupportedArch" value="false"/>
|
||||
</isArch>
|
||||
|
||||
<isArch arch="arm64-v8a">
|
||||
<setBool result="bSupportedArch" value="true"/>
|
||||
</isArch>
|
||||
|
||||
<isArch arch="x86">
|
||||
<setBool result="bSupportedArch" value="false"/>
|
||||
</isArch>
|
||||
|
||||
<isArch arch="x86_64">
|
||||
<setBool result="bSupportedArch" value="false"/>
|
||||
</isArch>
|
||||
|
||||
<if condition="bSupportedArch">
|
||||
<false>
|
||||
<log text="SenseGloveAndroid [WARN]: this architecture is not supported!"/>
|
||||
</false>
|
||||
</if>
|
||||
</init>
|
||||
|
||||
<!--
|
||||
<prebuildCopies>
|
||||
<copyDir src="$S(PluginDir)/Private/Java" dst="$S(BuildDir)/src/com/senseglove/sgconnect" />
|
||||
</prebuildCopies>
|
||||
-->
|
||||
|
||||
<resourceCopies>
|
||||
<isArch arch="arm64-v8a">
|
||||
<if condition="Distribution">
|
||||
<true>
|
||||
<!--
|
||||
<copyFile src="$S(PluginDir)/ThirdParty/lib/oculus/release/somelib.so"
|
||||
dst="$S(BuildDir)/libs/$S(Architecture)/somelib.so" />
|
||||
-->
|
||||
</true>
|
||||
<false>
|
||||
<!--
|
||||
<copyFile src="$S(PluginDir)/ThirdParty/lib/oculus/debug/somelib.so"
|
||||
dst="$S(BuildDir)/libs/$S(Architecture)/somelib.so" />
|
||||
-->
|
||||
</false>
|
||||
</if>
|
||||
</isArch>
|
||||
|
||||
<copyFile src="$S(PluginDir)/../ThirdParty/android/sgconnect.jar" dst="$S(BuildDir)/gradle/app/libs/sgconnect.jar" />
|
||||
</resourceCopies>
|
||||
|
||||
<gradleProperties>
|
||||
<insert>
|
||||
<!--android.useAndroidX=true
|
||||
android.enableJetifier=true-->
|
||||
kapt.incremental.apt=true
|
||||
</insert>
|
||||
</gradleProperties>
|
||||
|
||||
<proguardAdditions>
|
||||
<insert>
|
||||
|
||||
<!-- Disable obfuscation for SenseGlove classes -->
|
||||
-dontwarn com.senseglove.**
|
||||
-keep class com.senseglove.** { *; }
|
||||
-keep interface com.senseglove.** { *; }
|
||||
-keep public class com.senseglove.sgconnect.** { public protected *; }
|
||||
|
||||
<!-- Disable obfuscation for AndroidX classes -->
|
||||
<!---dontwarn androidx.**
|
||||
-keep class androidx.** { *; }
|
||||
-keep interface androidx.** { *; }-->
|
||||
|
||||
</insert>
|
||||
</proguardAdditions>
|
||||
|
||||
<soLoadLibrary>
|
||||
<!--
|
||||
<loadLibrary name="somelib" failmsg="SenseGlove [WARN]: somelib.so library failed to load!" />
|
||||
-->
|
||||
</soLoadLibrary>
|
||||
|
||||
<androidManifestUpdates>
|
||||
|
||||
<!-- For target SDK 31 update the SplashActivity activity -->
|
||||
<loopElements tag="activity">
|
||||
<setStringFromAttribute result="activityName" tag="$" name="android:name"/>
|
||||
<setBoolIsEqual result="bSplashActivity" arg1="$S(activityName)" arg2="com.epicgames.ue4.SplashActivity"/>
|
||||
<if condition="bSplashActivity">
|
||||
<true>
|
||||
<addAttribute tag="$" name="android:exported" value="true"/>
|
||||
</true>
|
||||
</if>
|
||||
</loopElements>
|
||||
|
||||
<addElements tag="application">
|
||||
<!--
|
||||
<addAttribute tag="application" name="android:requestSomeThingHere" value="true"/>
|
||||
-->
|
||||
</addElements>
|
||||
|
||||
<addPermission android:name="android.permission.BLUETOOTH"/>
|
||||
<addPermission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
<addPermission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
|
||||
<addPermission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
|
||||
</androidManifestUpdates>
|
||||
|
||||
<!--
|
||||
<AARImports>
|
||||
<insertValue value="repository $S(PluginDir)/../../ThirdParty/android"/>
|
||||
<insertNewline/>
|
||||
<insertValue value="com.senseglove.sgconnect,sgconnect-android,release" />
|
||||
<insertNewline/>
|
||||
</AARImports>
|
||||
-->
|
||||
|
||||
<buildGradleAdditions>
|
||||
<insert>
|
||||
ext {
|
||||
android {
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation files('libs/sgconnect.jar')
|
||||
}
|
||||
|
||||
</insert>
|
||||
</buildGradleAdditions>
|
||||
|
||||
<baseBuildGradleAdditions>
|
||||
<insert>
|
||||
allprojects {
|
||||
def mappings = [
|
||||
]
|
||||
beforeEvaluate {
|
||||
}
|
||||
}
|
||||
</insert>
|
||||
</baseBuildGradleAdditions>
|
||||
|
||||
<buildscriptGradleAdditions>
|
||||
</buildscriptGradleAdditions>
|
||||
|
||||
<gradleCopies>
|
||||
</gradleCopies>
|
||||
|
||||
<buildXmlPropertyAdditions>
|
||||
</buildXmlPropertyAdditions>
|
||||
|
||||
<minimumSDKAPI>
|
||||
</minimumSDKAPI>
|
||||
|
||||
<gameActivityImportAdditions>
|
||||
<insert>
|
||||
import com.senseglove.*;
|
||||
</insert>
|
||||
</gameActivityImportAdditions>
|
||||
</root>
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SGBuildHacks/SGInclude_Connect_Android.h"
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SGBuildHacks/SGInclude_Core_Android.h"
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2022 SenseGlove
|
||||
* Copyright (c) 2020 - 2023 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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user