mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f313e9625d | ||
|
|
9b774d768c | ||
|
|
6c28e18788 | ||
|
|
9c7ccac5ff | ||
|
|
020ee98e47 | ||
|
|
cd5c4dc219 | ||
|
|
04a777a98e |
109
.github/workflows/gradle.yaml
vendored
109
.github/workflows/gradle.yaml
vendored
@@ -38,6 +38,7 @@ jobs:
|
||||
- name: Test with Gradle
|
||||
run: ./gradlew test
|
||||
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -66,9 +67,20 @@ jobs:
|
||||
# A file, directory or wildcard pattern that describes what to upload
|
||||
path: server/build/libs/*
|
||||
|
||||
bundle:
|
||||
- name: Upload to draft release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
server/build/libs/*
|
||||
|
||||
|
||||
bundle-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: build
|
||||
needs: [build, test]
|
||||
if: contains(fromJSON('["workflow_dispatch", "create"]'), github.event_name)
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -131,9 +143,27 @@ jobs:
|
||||
name: SlimeVR-GUI-AppImage
|
||||
path: target/release/bundle/appimage/slimevr*.AppImage
|
||||
|
||||
- name: Prepare for release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
cp target/release/bundle/appimage/slimevr*.AppImage ./SlimeVR-amd64.appimage
|
||||
cp target/release/bundle/deb/slimevr*.deb ./SlimeVR-amd64.deb
|
||||
|
||||
- name: Upload to draft release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
./SlimeVR-amd64.appimage
|
||||
./SlimeVR-amd64.deb
|
||||
|
||||
|
||||
bundle-mac:
|
||||
runs-on: macos-latest
|
||||
needs: build
|
||||
needs: [build, test]
|
||||
if: contains(fromJSON('["workflow_dispatch", "create"]'), github.event_name)
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -179,3 +209,76 @@ jobs:
|
||||
with:
|
||||
name: SlimeVR-GUI-MacDmg
|
||||
path: target/release/bundle/dmg/slimevr.dmg
|
||||
|
||||
- name: Prepare for release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
cp target/release/bundle/dmg/slimevr.dmg ./SlimeVR-mac.dmg
|
||||
|
||||
- name: Upload to draft release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
./SlimeVR-mac.dmg
|
||||
|
||||
|
||||
bundle-windows:
|
||||
runs-on: windows-latest
|
||||
needs: [build, test]
|
||||
if: contains(fromJSON('["workflow_dispatch", "create"]'), github.event_name)
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: "SlimeVR-Server"
|
||||
path: server/build/libs/
|
||||
|
||||
- name: Cache cargo dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: "windows-latest"
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
npm run skipbundler
|
||||
|
||||
- name: Bundle to zips
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir SlimeVR
|
||||
cp gui/src-tauri/icons/icon.ico ./SlimeVR/run.ico
|
||||
cp server/build/libs/slimevr.jar ./SlimeVR/slimevr.jar
|
||||
cp server/resources/* ./SlimeVR/
|
||||
cp target/release/slimevr.exe ./SlimeVR/
|
||||
7z a -tzip SlimeVR-win64.zip ./SlimeVR/
|
||||
|
||||
mv ./SlimeVR/slimevr.exe ./SlimeVR/slimevr-ui.exe
|
||||
7z a -tzip SlimeVR.zip ./SlimeVR/
|
||||
|
||||
- uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: SlimeVR-GUI-Windows
|
||||
path: ./SlimeVR*.zip
|
||||
|
||||
- name: Upload to draft release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
./SlimeVR-win64.zip
|
||||
./SlimeVR.zip
|
||||
|
||||
@@ -60,6 +60,8 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="0.6.2" date="2023-02-17"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.2</url></release>
|
||||
<release version="0.6.1" date="2023-02-12"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.1</url></release>
|
||||
<release version="0.6.0" date="2023-01-05"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.0</url></release>
|
||||
<release version="0.5.1" date="2022-12-12"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.5.1</url></release>
|
||||
<release version="0.5.0" date="2022-12-07"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.5.0</url></release>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import classNames from 'classnames';
|
||||
import { IPv4 } from 'ip-num/IPNumber';
|
||||
import { MouseEventHandler, ReactNode, useState, useMemo } from 'react';
|
||||
import { MouseEventHandler, ReactNode, useMemo, useState } from 'react';
|
||||
import {
|
||||
TrackerDataT,
|
||||
TrackerIdT,
|
||||
TrackerStatus as TrackerStatusEnum,
|
||||
TrackerStatus as TrackerStatusEnum
|
||||
} from 'solarxr-protocol';
|
||||
import { FlatDeviceTracker } from '../../hooks/app';
|
||||
import { useConfig } from '../../hooks/config';
|
||||
import { useTracker } from '../../hooks/tracker';
|
||||
import { FootIcon } from '../commons/icon/FootIcon';
|
||||
import { Typography } from '../commons/Typography';
|
||||
import { formatVector3 } from '../utils/formatting';
|
||||
import { TrackerBattery } from './TrackerBattery';
|
||||
import { TrackerStatus } from './TrackerStatus';
|
||||
import { TrackerWifi } from './TrackerWifi';
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { formatVector3 } from '../utils/formatting';
|
||||
import { useConfig } from '../../hooks/config';
|
||||
|
||||
enum DisplayColumn {
|
||||
NAME,
|
||||
@@ -137,7 +137,7 @@ export function RowContainer({
|
||||
)}px #BB8AE5`,
|
||||
}}
|
||||
className={classNames(
|
||||
'min-h-[50px] flex flex-col justify-center px-3',
|
||||
'h-[50px] flex flex-col justify-center px-3',
|
||||
rounded === 'left' && 'rounded-l-lg',
|
||||
rounded === 'right' && 'rounded-r-lg',
|
||||
hover ? 'bg-background-50 cursor-pointer' : 'bg-background-60'
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { KeyValuesT, MessageT, Payload, Topic } from 'solarxr-protocol';
|
||||
import {
|
||||
OVERLAY_DISPLAY_SETTINGS_TOPIC,
|
||||
PayloadData,
|
||||
usePubSub,
|
||||
usePubSub
|
||||
} from '../../hooks/pubSub';
|
||||
import { CheckBox } from '../commons/Checkbox';
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { Typography } from '../commons/Typography';
|
||||
|
||||
export function OverlayWidget() {
|
||||
const { l10n } = useLocalization();
|
||||
const { publish, subscribe, keyValues } = usePubSub();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { reset, control, handleSubmit, watch } = useForm<{
|
||||
isVisible: boolean;
|
||||
isMirrored: boolean;
|
||||
@@ -26,6 +27,7 @@ export function OverlayWidget() {
|
||||
subscribe(
|
||||
OVERLAY_DISPLAY_SETTINGS_TOPIC,
|
||||
(payload: PayloadData, type: Payload) => {
|
||||
setLoading(false);
|
||||
if (type !== Payload.KeyValues) throw new Error('Invalid payload');
|
||||
const obj = keyValues(payload);
|
||||
reset({
|
||||
@@ -63,7 +65,7 @@ export function OverlayWidget() {
|
||||
publish(message);
|
||||
};
|
||||
|
||||
return (
|
||||
return !loading ? (
|
||||
<form className="bg-background-60 flex flex-col w-full rounded-md px-2">
|
||||
<div className="mt-2 px-1">
|
||||
<Typography color="secondary">
|
||||
@@ -83,5 +85,7 @@ export function OverlayWidget() {
|
||||
label={l10n.getString('widget-overlay-is_mirrored_label')}
|
||||
></CheckBox>
|
||||
</form>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
BaseDirectory,
|
||||
createDir,
|
||||
readTextFile,
|
||||
renameFile,
|
||||
writeFile,
|
||||
} from '@tauri-apps/api/fs';
|
||||
import { BaseDirectory, readTextFile } from '@tauri-apps/api/fs';
|
||||
|
||||
import { createContext, useContext, useRef, useState } from 'react';
|
||||
import { DeveloperModeWidgetForm } from '../components/widgets/DeveloperModeWidget';
|
||||
@@ -53,14 +47,7 @@ export function useConfigProvider(): ConfigContext {
|
||||
|
||||
if (!debounceTimer.current) {
|
||||
debounceTimer.current = setTimeout(async () => {
|
||||
await createDir('', { dir: BaseDirectory.App, recursive: true });
|
||||
await writeFile(
|
||||
{ contents: JSON.stringify(newConfig), path: 'config.json.tmp' },
|
||||
{ dir: BaseDirectory.App }
|
||||
);
|
||||
await renameFile('config.json.tmp', 'config.json', {
|
||||
dir: BaseDirectory.App,
|
||||
});
|
||||
localStorage.setItem('config.json', JSON.stringify(newConfig));
|
||||
debounceTimer.current = null;
|
||||
}, 10);
|
||||
}
|
||||
@@ -73,9 +60,21 @@ export function useConfigProvider(): ConfigContext {
|
||||
loadConfig: async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const json = await readTextFile('config.json', {
|
||||
dir: BaseDirectory.App,
|
||||
});
|
||||
const migrated = localStorage.getItem('configMigrated');
|
||||
if (!migrated) {
|
||||
const oldConfig = await readTextFile('config.json', {
|
||||
dir: BaseDirectory.App,
|
||||
}).catch(() => null);
|
||||
|
||||
if (oldConfig) localStorage.setItem('config.json', oldConfig);
|
||||
|
||||
localStorage.setItem('configMigrated', 'true');
|
||||
}
|
||||
|
||||
const json = localStorage.getItem('config.json');
|
||||
|
||||
if (!json) throw new Error('Config has ceased existing for some reason');
|
||||
|
||||
const loadedConfig = JSON.parse(json);
|
||||
set(loadedConfig);
|
||||
setLoading(false);
|
||||
|
||||
@@ -149,6 +149,30 @@ public class CurrentVRConfigConverter implements VersionedModelConverter {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (version < 7) {
|
||||
// Chest, hip, and elbow offsets now go the opposite direction
|
||||
ObjectNode skeletonNode = (ObjectNode) modelData.get("skeleton");
|
||||
if (skeletonNode != null) {
|
||||
ObjectNode offsetsNode = (ObjectNode) skeletonNode.get("offsets");
|
||||
if (offsetsNode != null) {
|
||||
offsetsNode
|
||||
.set(
|
||||
"chestOffset",
|
||||
new FloatNode(-offsetsNode.get("chestOffset").floatValue())
|
||||
);
|
||||
offsetsNode
|
||||
.set(
|
||||
"hipOffset",
|
||||
new FloatNode(-offsetsNode.get("hipOffset").floatValue())
|
||||
);
|
||||
offsetsNode
|
||||
.set(
|
||||
"elbowOffset",
|
||||
new FloatNode(-offsetsNode.get("elbowOffset").floatValue())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modelData;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Map;
|
||||
|
||||
|
||||
@JsonVersionedModel(
|
||||
currentVersion = "6", defaultDeserializeToVersion = "6", toCurrentConverterClass = CurrentVRConfigConverter.class
|
||||
currentVersion = "7", defaultDeserializeToVersion = "7", toCurrentConverterClass = CurrentVRConfigConverter.class
|
||||
)
|
||||
public class VRConfig {
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ public class SkeletonConfigManager {
|
||||
case CHEST_TRACKER -> setNodeOffset(
|
||||
nodeOffset,
|
||||
0,
|
||||
getOffset(SkeletonConfigOffsets.CHEST_OFFSET)
|
||||
-getOffset(SkeletonConfigOffsets.CHEST_OFFSET)
|
||||
- getOffset(SkeletonConfigOffsets.CHEST),
|
||||
-getOffset(SkeletonConfigOffsets.SKELETON_OFFSET)
|
||||
);
|
||||
@@ -204,7 +204,7 @@ public class SkeletonConfigManager {
|
||||
case HIP_TRACKER -> setNodeOffset(
|
||||
nodeOffset,
|
||||
0,
|
||||
getOffset(SkeletonConfigOffsets.HIP_OFFSET),
|
||||
-getOffset(SkeletonConfigOffsets.HIP_OFFSET),
|
||||
-getOffset(SkeletonConfigOffsets.SKELETON_OFFSET)
|
||||
);
|
||||
case LEFT_HIP -> setNodeOffset(
|
||||
@@ -282,7 +282,7 @@ public class SkeletonConfigManager {
|
||||
case LEFT_ELBOW_TRACKER, RIGHT_ELBOW_TRACKER -> setNodeOffset(
|
||||
nodeOffset,
|
||||
0,
|
||||
getOffset(SkeletonConfigOffsets.ELBOW_OFFSET),
|
||||
-getOffset(SkeletonConfigOffsets.ELBOW_OFFSET),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1177,16 +1177,18 @@ public class HumanSkeleton {
|
||||
) {
|
||||
// Clone the hip since we're modifying it and returning it
|
||||
hip = hip.clone();
|
||||
// Clone the knees here because otherwise it doesn't work because Java
|
||||
leftKnee = leftKnee.clone();
|
||||
rightKnee = rightKnee.clone();
|
||||
|
||||
|
||||
// Get the knees' rotation relative to where we expect them to be.
|
||||
// The angle between your knees and hip can be over 180 degrees...
|
||||
hip.mult(FORWARD_QUATERNION, rotBuf1);
|
||||
if (rotBuf1.dot(leftKnee) < 0.0f) {
|
||||
leftKnee = leftKnee.clone();
|
||||
leftKnee.negateLocal();
|
||||
}
|
||||
if (rotBuf1.dot(rightKnee) < 0.0f) {
|
||||
rightKnee = rightKnee.clone();
|
||||
rightKnee.negateLocal();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user