Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2bbe7097c | ||
|
|
415a07461e | ||
|
|
4bd31fb02f | ||
|
|
2bc50b2bc2 | ||
|
|
e37b11844f | ||
|
|
92f709e2f9 | ||
|
|
7fe3d82540 |
4
.github/workflows/gradle.yaml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Get tags
|
||||
run: git fetch --tags origin --recurse-submodules=no
|
||||
run: git fetch --tags origin --recurse-submodules=no --force
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Get tags
|
||||
run: git fetch --tags origin --recurse-submodules=no
|
||||
run: git fetch --tags origin --recurse-submodules=no --force
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"react": "^18.0.0",
|
||||
"react-dev-utils": "^12.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.29.0",
|
||||
"react-modal": "3.15.1",
|
||||
"react-responsive": "^9.0.2",
|
||||
@@ -77,6 +78,7 @@
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"@types/react-helmet": "^6.1.6",
|
||||
"@types/react-modal": "3.13.1",
|
||||
"@types/three": "^0.148.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
|
||||
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 6.3 KiB |
@@ -1,5 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-miterlimit="10" version="1.1" viewBox="0 0 380 380" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>svg { background-color: #663499; }</style>
|
||||
<rect id="bg" width="100%" height="100%" fill="#663499"/><g id="logo" fill="none" stroke="#fff"><path id="left" d="m72.867 191.74 37-39 39 36" stroke-width="13.62px"/><path id="right" d="m208.87 187.74 38-35 36 38" stroke-width="13.62px"/><path id="outer" d="m56.867 253.74s130.61-31.182 248 5c13.45 4.146 20.244 2.975 20-8s1.909-126.06-46-131" stroke-linecap="square" stroke-width="17px"/></g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" stroke-miterlimit="10" clip-rule="evenodd" version="1.1" viewBox="0 0 380 380" xml:space="preserve"><style>svg{background-color:#663499}</style><rect id="bg" width="100%" height="100%" fill="#663499"/><g id="logo" fill="none" stroke="#fff"><path id="left" stroke-width="13.62" d="m72.867 191.74 37-39 39 36"/><path id="right" stroke-width="13.62" d="m208.87 187.74 38-35 36 38"/><path id="outer" stroke-linecap="square" stroke-width="17" d="m56.867 253.74s130.61-31.182 248 5c13.45 4.146 20.244 2.975 20-8s1.909-126.06-46-131"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 598 B |
@@ -52,6 +52,7 @@ import { VRModePage } from './components/vr-mode/VRModePage';
|
||||
import { InterfaceSettings } from './components/settings/pages/InterfaceSettings';
|
||||
import { error, log } from './utils/logging';
|
||||
import { AppLayout } from './AppLayout';
|
||||
import { Preload } from './components/Preload';
|
||||
|
||||
export const GH_REPO = 'SlimeVR/SlimeVR-Server';
|
||||
export const VersionContext = createContext('');
|
||||
@@ -252,6 +253,7 @@ export default function App() {
|
||||
<StatusProvider>
|
||||
<VersionContext.Provider value={updateFound}>
|
||||
<div className="h-full w-full text-standard bg-background-80 text-background-10">
|
||||
<Preload />
|
||||
<div className="flex-col h-full">
|
||||
{!websocketAPI.isConnected && (
|
||||
<>
|
||||
|
||||
48
gui/src/components/Preload.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Helmet } from 'react-helmet';
|
||||
export function Preload() {
|
||||
return (
|
||||
<Helmet>
|
||||
<link rel="preload" href="/images/front-standing-pose.webp" as="image" />
|
||||
<link rel="preload" href="/images/slime-girl.webp" as="image" />
|
||||
<link rel="preload" href="/images/mounting-reset-pose.webp" as="image" />
|
||||
<link rel="preload" href="/images/reset-pose.webp" as="image" />
|
||||
<link rel="preload" href="/images/slimes.webp" as="image" />
|
||||
|
||||
<link
|
||||
rel="preload"
|
||||
href="/sounds/quick-reset-started-sound.mp3"
|
||||
as="audio"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/sounds/full-reset-started-sound.mp3"
|
||||
as="audio"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/sounds/mounting-reset-started-sound.mp3"
|
||||
as="audio"
|
||||
/>
|
||||
<link rel="preload" href="/sounds/first-tap.mp3" as="audio" />
|
||||
<link rel="preload" href="/sounds/second-tap.mp3" as="audio" />
|
||||
<link rel="preload" href="/sounds/third-tap.mp3" as="audio" />
|
||||
<link rel="preload" href="/sounds/fourth-tap.mp3" as="audio" />
|
||||
<link rel="preload" href="/sounds/fifth-tap.mp3" as="audio" />
|
||||
<link rel="preload" href="/sounds/end-tap.mp3" as="audio" />
|
||||
<link rel="preload" href="/sounds/tapextrasetup.mp3" as="audio" />
|
||||
|
||||
<link
|
||||
rel="preload"
|
||||
href="/models/tracker.gltf"
|
||||
as="fetch"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/models/extension.gltf"
|
||||
as="fetch"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
@@ -15,24 +15,6 @@ const tapSetupSound5 = new Audio('/sounds/fifth-tap.mp3');
|
||||
const tapSetupSoundEnd = new Audio('/sounds/end-tap.mp3');
|
||||
const tapSetupExtraSound = new Audio('/sounds/tapextrasetup.mp3');
|
||||
|
||||
const sounds = [
|
||||
quickResetStartedSound,
|
||||
fullResetStartedSound,
|
||||
mountingResetStartedSound,
|
||||
tapSetupSound1,
|
||||
tapSetupSound2,
|
||||
tapSetupSound3,
|
||||
tapSetupSound4,
|
||||
tapSetupSound5,
|
||||
tapSetupSoundEnd,
|
||||
tapSetupExtraSound,
|
||||
];
|
||||
|
||||
sounds.forEach((s) => {
|
||||
s.play();
|
||||
setTimeout(() => s.pause(), 10);
|
||||
});
|
||||
|
||||
function restartAndPlay(audio: HTMLAudioElement, volume: number) {
|
||||
audio.volume = Math.min(1, Math.pow(volume, Math.E) + 0.05);
|
||||
if (audio.paused) {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig, PluginOption } from 'vite';
|
||||
import { execSync } from 'child_process';
|
||||
import path from 'path'
|
||||
import path from 'path';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
|
||||
const commitHash = execSync('git rev-parse --verify --short HEAD').toString().trim();
|
||||
const versionTag = execSync('git --no-pager tag --points-at HEAD').toString().trim();
|
||||
const versionTag = execSync('git --no-pager tag --sort -taggerdate --points-at HEAD')
|
||||
.toString()
|
||||
.split('\n')[0]
|
||||
.trim();
|
||||
// If not empty then it's not clean
|
||||
const gitClean = execSync('git status --porcelain').toString() ? false : true;
|
||||
|
||||
@@ -51,7 +54,7 @@ export default defineConfig({
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src')
|
||||
}
|
||||
}
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
38
package-lock.json
generated
@@ -48,6 +48,7 @@
|
||||
"react": "^18.0.0",
|
||||
"react-dev-utils": "^12.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.29.0",
|
||||
"react-modal": "3.15.1",
|
||||
"react-responsive": "^9.0.2",
|
||||
@@ -65,6 +66,7 @@
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"@types/react-helmet": "^6.1.6",
|
||||
"@types/react-modal": "3.13.1",
|
||||
"@types/three": "^0.148.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
@@ -3394,6 +3396,15 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-helmet": {
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.6.tgz",
|
||||
"integrity": "sha512-ZKcoOdW/Tg+kiUbkFCBtvDw0k3nD4HJ/h/B9yWxN4uDO8OkRksWTO+EL+z/Qu3aHTeTll3Ro0Cc/8UhwBCMG5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-modal": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.13.1.tgz",
|
||||
@@ -9333,6 +9344,25 @@
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
||||
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
|
||||
},
|
||||
"node_modules/react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"node_modules/react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"dependencies": {
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.45.4",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.45.4.tgz",
|
||||
@@ -9446,6 +9476,14 @@
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-side-effect": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
|
||||
"integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-use-measure": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz",
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB |
@@ -1071,8 +1071,8 @@ class HumanSkeleton(
|
||||
BoneType.RIGHT_FOOT_TRACKER -> trackerRightFootNode
|
||||
BoneType.LEFT_SHOULDER -> leftShoulderTailNode
|
||||
BoneType.RIGHT_SHOULDER -> rightShoulderTailNode
|
||||
BoneType.LEFT_UPPER_ARM -> if (!isTrackingLeftArmFromController) leftElbowNode else null
|
||||
BoneType.RIGHT_UPPER_ARM -> if (!isTrackingLeftArmFromController) rightElbowNode else null
|
||||
BoneType.LEFT_UPPER_ARM -> leftElbowNode
|
||||
BoneType.RIGHT_UPPER_ARM -> rightElbowNode
|
||||
BoneType.LEFT_ELBOW_TRACKER -> trackerLeftElbowNode
|
||||
BoneType.RIGHT_ELBOW_TRACKER -> trackerRightElbowNode
|
||||
BoneType.LEFT_LOWER_ARM -> if (isTrackingLeftArmFromController) leftElbowNode else leftWristNode
|
||||
|
||||
@@ -57,15 +57,19 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
|
||||
private fun setUpNewConnection(handshakePacket: DatagramPacket, handshake: UDPPacket3Handshake) {
|
||||
LogManager.info("[TrackerServer] Handshake received from ${handshakePacket.address}:${handshakePacket.port}")
|
||||
val addr = handshakePacket.address
|
||||
val socketAddr = handshakePacket.socketAddress
|
||||
|
||||
// Get a connection either by an existing one, or by creating a new one
|
||||
val connection: UDPDevice = synchronized(connections) {
|
||||
connectionsByMAC[handshake.macString]?.apply {
|
||||
// Look for an existing connection by the MAC address and update the
|
||||
// connection information
|
||||
connectionsByAddress.remove(address)
|
||||
address = handshakePacket.socketAddress
|
||||
address = socketAddr
|
||||
lastPacketNumber = 0
|
||||
ipAddress = addr
|
||||
name = handshake.macString?.let { "udp://$it" }
|
||||
descriptiveName = "udp:/${handshakePacket.address}"
|
||||
descriptiveName = "udp:/$addr"
|
||||
firmwareBuild = handshake.firmwareBuild
|
||||
connectionsByAddress[address] = this
|
||||
|
||||
@@ -73,7 +77,28 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
|
||||
LogManager
|
||||
.info(
|
||||
"""
|
||||
[TrackerServer] Tracker $i handed over to address ${handshakePacket.socketAddress}.
|
||||
[TrackerServer] Tracker $i handed over to address $socketAddr.
|
||||
Board type: ${handshake.boardType},
|
||||
imu type: ${handshake.imuType},
|
||||
firmware: ${handshake.firmware} ($firmwareBuild),
|
||||
mac: ${handshake.macString},
|
||||
name: $name
|
||||
""".trimIndent()
|
||||
)
|
||||
} ?: connectionsByAddress[socketAddr]?.apply {
|
||||
// Look for an existing connection by the socket address (IP and port)
|
||||
// and update the connection information
|
||||
lastPacketNumber = 0
|
||||
ipAddress = addr
|
||||
name = handshake.macString?.let { "udp://$it" }
|
||||
?: "udp:/$addr"
|
||||
descriptiveName = "udp:/$addr"
|
||||
firmwareBuild = handshake.firmwareBuild
|
||||
val i = connections.indexOf(this)
|
||||
LogManager
|
||||
.info(
|
||||
"""
|
||||
[TrackerServer] Tracker $i reconnected from address $socketAddr.
|
||||
Board type: ${handshake.boardType},
|
||||
imu type: ${handshake.imuType},
|
||||
firmware: ${handshake.firmware} ($firmwareBuild),
|
||||
@@ -83,8 +108,9 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
|
||||
)
|
||||
}
|
||||
} ?: run {
|
||||
// No existing connection could be found, create a new one
|
||||
val connection = UDPDevice(
|
||||
handshakePacket.socketAddress,
|
||||
socketAddr,
|
||||
addr,
|
||||
handshake.macString ?: addr.hostAddress,
|
||||
handshake.boardType,
|
||||
@@ -99,53 +125,31 @@ class TrackersUDPServer(private val port: Int, name: String, private val tracker
|
||||
NetworkProtocol.SLIMEVR_RAW
|
||||
}
|
||||
connection.name = handshake.macString?.let { "udp://$it" }
|
||||
?: "udp:/${handshakePacket.address}"
|
||||
?: "udp:/$addr"
|
||||
// TODO: The missing slash in udp:// was intended because InetAddress.toString()
|
||||
// returns "hostname/address" but it wasn't known that if hostname is empty
|
||||
// string it just looks like "/address" lol.
|
||||
// Fixing this would break config!
|
||||
connection.descriptiveName = "udp:/${handshakePacket.address}"
|
||||
connection.descriptiveName = "udp:/$addr"
|
||||
synchronized(connections) {
|
||||
if (handshake.macString != null && connectionsByMAC.containsKey(handshake.macString)) {
|
||||
val previousConnection = connectionsByMAC[handshake.macString]!!
|
||||
val i = connections.indexOf(previousConnection)
|
||||
connectionsByAddress.remove(previousConnection.address)
|
||||
previousConnection.lastPacketNumber = 0
|
||||
previousConnection.ipAddress = addr
|
||||
previousConnection.address = handshakePacket.socketAddress
|
||||
previousConnection.name = connection.name
|
||||
previousConnection.descriptiveName = connection.descriptiveName
|
||||
connectionsByAddress[handshakePacket.socketAddress] = previousConnection
|
||||
LogManager
|
||||
.info(
|
||||
"""
|
||||
[TrackerServer] Tracker $i handed over to address ${handshakePacket.socketAddress}.
|
||||
Board type: ${handshake.boardType},
|
||||
imu type: ${handshake.imuType},
|
||||
firmware: ${handshake.firmware} (${connection.firmwareBuild}),
|
||||
mac: ${handshake.macString},
|
||||
name: ${previousConnection.name}
|
||||
""".trimIndent()
|
||||
)
|
||||
} else {
|
||||
val i = connections.size
|
||||
connections.add(connection)
|
||||
connectionsByAddress[handshakePacket.socketAddress] = connection
|
||||
if (handshake.macString != null) {
|
||||
connectionsByMAC[handshake.macString!!] = connection
|
||||
}
|
||||
LogManager
|
||||
.info(
|
||||
"""
|
||||
[TrackerServer] Tracker $i handed over to address ${handshakePacket.socketAddress}.
|
||||
Board type: ${handshake.boardType},
|
||||
imu type: ${handshake.imuType},
|
||||
firmware: ${handshake.firmware} (${connection.firmwareBuild}),
|
||||
mac: ${handshake.macString},
|
||||
name: ${connection.name}
|
||||
""".trimIndent()
|
||||
)
|
||||
// Register the new connection
|
||||
val i = connections.size
|
||||
connections.add(connection)
|
||||
connectionsByAddress[socketAddr] = connection
|
||||
if (handshake.macString != null) {
|
||||
connectionsByMAC[handshake.macString!!] = connection
|
||||
}
|
||||
LogManager
|
||||
.info(
|
||||
"""
|
||||
[TrackerServer] Tracker $i connected from address $socketAddr.
|
||||
Board type: ${handshake.boardType},
|
||||
imu type: ${handshake.imuType},
|
||||
firmware: ${handshake.firmware} (${connection.firmwareBuild}),
|
||||
mac: ${handshake.macString},
|
||||
name: ${connection.name}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
if (connection.protocol == NetworkProtocol.OWO_LEGACY || connection.firmwareBuild < 9) {
|
||||
// Set up new sensor for older firmware.
|
||||
|
||||
@@ -81,8 +81,8 @@ buildConfig {
|
||||
packageName("dev.slimevr.desktop")
|
||||
|
||||
val gitVersionTag = providers.exec {
|
||||
commandLine("git", "--no-pager", "tag", "--points-at", "HEAD")
|
||||
}.standardOutput.asText.get()
|
||||
commandLine("git", "--no-pager", "tag", "--sort", "-taggerdate", "--points-at", "HEAD")
|
||||
}.standardOutput.asText.get().split('\n').first()
|
||||
buildConfigField("String", "GIT_COMMIT_HASH", "\"${grgit.head().abbreviatedId}\"")
|
||||
buildConfigField("String", "GIT_VERSION_TAG", "\"${gitVersionTag.trim()}\"")
|
||||
buildConfigField("boolean", "GIT_CLEAN", grgit.status().isClean.toString())
|
||||
|
||||