diff --git a/.gitattributes b/.gitattributes
index 58aa9dfe..d2a0afbc 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -43,4 +43,8 @@ Source/ThirdParty/**/* filter=lfs diff=lfs merge=lfs -text
Handbook/dist/**/* filter=lfs diff=lfs merge=lfs -text
# Except
.gitignore filter= diff= merge= text
-.gitattributes filter= diff= merge= text
\ No newline at end of file
+.gitattributes filter= diff= merge= text
+
+# LFS: sgum-packager Linux and Windows binaries
+Packager/sgum-packager filter=lfs diff=lfs merge=lfs -text
+Packager/sgum-packager.exe filter=lfs diff=lfs merge=lfs -text
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index f8e7af19..e7ba676d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,4 +128,8 @@ DerivedDataCache/*
# The Handbook
Documentation/
-Handbook/book/
\ No newline at end of file
+Handbook/book/
+
+# sgum-packager
+# Do not ignore the sgum-packager Windows binary
+!Packager/sgum-packager.exe
\ No newline at end of file
diff --git a/Handbook/src/appendix/changelog.md b/Handbook/src/appendix/changelog.md
index bdc3a262..820ef1d0 100644
--- a/Handbook/src/appendix/changelog.md
+++ b/Handbook/src/appendix/changelog.md
@@ -67,6 +67,7 @@ This is a minor release focusing mainly on bringing OpenXR-compatible hand track
- Added SGWristTrackingSettingsOverrides config structured by the new settings override system.
- Added support for Android API level 32 in addition to the API level 29.
- Introduced the SenseGlove Unreal Engine Handbook as an attempt at documenting the SenseGlove Unreal Engine Plugin.
+- Merged the pack utility branch to the plugin's source code at /Packager.
### Fixed
@@ -109,6 +110,7 @@ This is a minor release focusing mainly on bringing OpenXR-compatible hand track
- Removed USGVirtualHandComponent::GetHandPose() and it's no longer possible to get the hand pose data from USGVirtualHandComponent as GetHandPose() has been removed. If you need it, you could always use the SenseGlove low-level API to retrieve it from the glove.
- Removed also GetFingerBoneName(), GetFingerBoneRefTransform(), GetFingerBoneRefRotation() and GetFingerBoneRefRotation() from USGVirtualHandComponent.
- Removed some remnants of UE 5.1 and older releases from the C++ code.
+- Removed the pack utility branch and merge it to the plugin's source code at /Packager.
### Known Issues
diff --git a/Packager/README.md b/Packager/README.md
new file mode 100644
index 00000000..9ff9993e
--- /dev/null
+++ b/Packager/README.md
@@ -0,0 +1,3 @@
+# SenseGlove Unreal Engine Marketplace Packager
+
+The `sgum-packager` utility is only meant to be used by the publisher of this plugin in to automatically package the plugin in adherence to the Unreal Engine Marketplace Guidelines.
\ No newline at end of file
diff --git a/Packager/sgum-packager b/Packager/sgum-packager
new file mode 100755
index 00000000..5c693b43
--- /dev/null
+++ b/Packager/sgum-packager
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7ce059e0ea05f93e18117f9aaea07ea70f121cb9ad1495c87f0caa96b829b7fa
+size 14696448
diff --git a/Packager/sgum-packager.exe b/Packager/sgum-packager.exe
new file mode 100755
index 00000000..4c5dc6f5
--- /dev/null
+++ b/Packager/sgum-packager.exe
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e906c5d4363e5d5447a0bc7741b0bbc6a2d538774a6d33a13668293af882e194
+size 15016448
diff --git a/Packager/sgum-packager.yml b/Packager/sgum-packager.yml
new file mode 100644
index 00000000..39aa6dad
--- /dev/null
+++ b/Packager/sgum-packager.yml
@@ -0,0 +1,185 @@
+# The SenseGlove Unreal Engine Marketplace Packager configuration file.
+# This file is in YAML format.
+# Although, the SenseGlove Unreal Engine Marketplace Packager is able to load
+# configurations from various file formats by detecting their file extensions.
+# Currently, the following configuration formats are supported:
+# - JSON
+# - TOML
+# - YAML
+# - HCL
+# - INI
+# - envfile
+# - Java properties config files
+
+
+Archive:
+
+ # Levels range from 1 (BestSpeed) to 9 (BestCompression); higher levels
+ # typically run slower but compress more. Level 0 (NoCompression) does not
+ # attempt any compression; it only adds the necessary DEFLATE framing. Level
+ # -1 (DefaultCompression) uses the default compression level. Level -2
+ # (HuffmanOnly) will use Huffman compression only, giving a very fast
+ # compression for all types of input, but sacrificing considerable compression
+ # efficiency.
+ CompressionLevel: 9
+
+ Directory:
+ Linux: /tmp/SenseGlove-Unreal/Archive
+ Windows: "%TEMP%\\SenseGlove-Unreal\\Archive"
+
+ # Brnach will be replaced with the Brnach name corresponding to the engine
+ # version, e.g. 5.1; and, version will be extracted from the latest tag, e.g.
+ # v1.0.4; producing SenseGlove-Unreal-5.1-v1.0.4.zip.
+ NameTemplate: "SenseGlove-Unreal-{BRANCH}-{VERSION}.zip"
+
+
+Deploy:
+
+ Repository: https://{USERNAME}:{PASSWORD}@dev.azure.com/SenseGlove/SenseGlove-Unreal/_git/SenseGlove-Unreal
+
+ UsernameEnvVar: SGUM_PACKAGER_REPOSITORY_USERNAME
+
+ PasswordEnvVar: SGUM_PACKAGER_REPOSITORY_PASSWORD
+
+ Branches:
+ - "5.4"
+ - "5.3"
+ - "5.2"
+
+ Exclusions:
+ - .git
+ - sgum-packager
+ - .clang-format
+ - .editorconfig
+ - .gitattributes
+ - .gitignore
+ - LICENSE-THIRD-PARTY.md
+ - LICENSE.md
+ - README.md
+
+
+Git:
+
+ Executable:
+ Linux: /usr/bin/git
+ Windows: "%PROGRAMFILES%\\Git\\bin\\git.exe"
+
+ CloneArguments:
+ - "--depth"
+ - "1"
+ - "--recurse-submodules"
+ - "--shallow-submodules"
+ - "--jobs"
+ - "16"
+
+ CloneDirectory:
+ Linux: /tmp/SenseGlove-Unreal/Repo
+ Windows: "%TEMP%\\SenseGlove-Unreal\\Repo"
+
+
+GoogleDrive:
+
+ LocalAuthServerPort: 11111
+
+ # Follow the instructions below in order to generate the credentials file:
+ #
+ # Enable the AP
+ # In the Google Cloud console, enable the Google Drive API.
+ # https://console.cloud.google.com/flows/enableapi?apiid=drive.googleapis.com
+ #
+ # Authorize credentials for a web application
+ # 1. In the Google Cloud console, go to Menu menu > APIs & Services > Credentials.
+ # https://console.cloud.google.com/apis/credentials
+ # 2. Click Create Credentials > OAuth client ID.
+ # 3. Click Application type > Desktop app.
+ # 4. In the Name field, type a name for the credential. This name is only shown in the Google Cloud console.
+ # 5. Click Create. The OAuth client created screen appears, showing your new Client ID and Client secret.
+ # 6. Click OK. The newly created credential appears under OAuth 2.0 Client IDs.
+ # 7. Save the downloaded JSON file as credentials.json, and move the file to your desired directory.
+ CredentialsFile:
+ Linux: ~/.config/sgum-packager/credentials.json
+ Windows: "%LOCALAPPDATA%\\sgum-packager\\credentials.json"
+
+ # This will be auto-generated on the first run
+ TokenFile:
+ Linux: ~/.config/sgum-packager/token.json
+ Windows: "%LOCALAPPDATA%\\sgum-packager\\token.json"
+
+ FolderNameTemplate: SenseGlove-Unreal-{VERSION}
+
+
+# Logging configurations
+Logging:
+
+ # The file to write logs to. Supports absolute path or relative paths
+ # containing environment variables as well.Backup log files will be retained
+ # in the same directory. It's optional and if left empty, no logs will be
+ # preserved and logs only go to screen instead of both screen and log files.
+ Filename:
+ Linux: ~/.cache/sgum-packager/sgum-packager.log
+ Windows: "%LOCALAPPDATA%\\sgum-packager\\sgum-packager.log"
+
+ # The maximum allowed size in MBs for the log file before it gets rotated.
+ # It defaults to 100 megabytes if not specified.
+ MaxSize: 100
+
+ # The maximum number of days to retain old log files based on the timestamp
+ # encoded in their filename. Note that a day is defined as 24 hours and may
+ # not exactly correspond to calendar days due to daylight savings, leap
+ # seconds, etc. If not specified, the default is not to remove old log files
+ # based on age.
+ MaxAge: 30
+
+ # Maximum number of old log files to retain. If not specified, the default is
+ # to retain all old log files (though MaxAge may still cause them to get
+ # deleted).
+ MaxBackups: 10
+
+ # Determines if the time used for formatting the timestamps in backup files is
+ # the computer's local time. The default is to use UTC time, if not specified.
+ LocalTime: true
+
+ # Determines whether the rotated log files should be compressed using the gzip
+ # compression algorithm, or not. The default is not to perform compression, in
+ # case it's not specified.
+ Compress: true
+
+
+Rocket:
+
+ RunUAT: true
+
+ UPluginFile: SenseGlove.uplugin
+
+ PackageDirectory: "%TEMP%\\SenseGlove-Unreal\\Rocket"
+
+ EnginePaths:
+ - "5.4": "C:\\OPT\\UE_5.4"
+ - "5.3": "C:\\OPT\\UE_5.3"
+ - "5.2": "C:\\OPT\\UE_5.2"
+
+ NDKPaths:
+ - "5.4": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393"
+ - "5.3": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393"
+ - "5.2": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393"
+
+
+Rsync:
+
+ Executable:
+ Linux: /usr/bin/rsync
+ Windows: "%PROGRAMFILES%\\cwrsync\\bin\\rsync.exe"
+
+ StageArguments:
+ - "--checksum"
+ - "--delete-after"
+ - "--ignore-errors"
+ - "--ignore-times"
+ - "--links"
+ - "--perms"
+ - "--recursive"
+ - "--verbose"
+
+ DestinationDirectory:
+ Linux: /tmp/SenseGlove-Unreal/Stage
+ Windows: "%TEMP%\\SenseGlove-Unreal\\Stage"
\ No newline at end of file