mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 10:11:59 +02:00
Compare commits
31 Commits
snap-seria
...
tauri-andr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9be83cf108 | ||
|
|
d7436e3972 | ||
|
|
bebc34d035 | ||
|
|
0f06ac0253 | ||
|
|
4568ebb41a | ||
|
|
2777d8af89 | ||
|
|
3f9b997ffa | ||
|
|
df379ee234 | ||
|
|
acd628637e | ||
|
|
155dbfbff1 | ||
|
|
eda3d74c54 | ||
|
|
4b9f393cee | ||
|
|
069da63d1f | ||
|
|
3fbe58b027 | ||
|
|
aa6b5ab028 | ||
|
|
b2ee4e0b5e | ||
|
|
34ab0c6252 | ||
|
|
a8116a7f35 | ||
|
|
8c65129bb4 | ||
|
|
acaf6a7679 | ||
|
|
8044a8a824 | ||
|
|
1ec03b83b6 | ||
|
|
44caf24126 | ||
|
|
a125195695 | ||
|
|
d27385dfa4 | ||
|
|
68bd670d7c | ||
|
|
42eda428ae | ||
|
|
6504ebb9fb | ||
|
|
6332615b08 | ||
|
|
e054c393ea | ||
|
|
85c30b9425 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -14,7 +14,7 @@
|
||||
/gui/src/i18n/ @ImUrX @Erimelowo
|
||||
/l10n.toml @ImUrX @Erimelowo
|
||||
|
||||
/gui/src/components/settings/ @Erimelowo @ImUrX
|
||||
/gui/src/components/settings/ @Erimelowo @ImUrX @loucass003
|
||||
|
||||
# Rust part of the GUI
|
||||
/gui/src-tauri/ @ImUrX
|
||||
|
||||
6
.github/workflows/build-gui.yml
vendored
6
.github/workflows/build-gui.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -59,13 +59,13 @@ jobs:
|
||||
BUILD_ARCH: ${{ endsWith(matrix.os, 'arm') && 'aarch64' || 'amd64' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- if: startsWith(matrix.os, 'ubuntu')
|
||||
name: Set up Linux dependencies
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.5.0
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.5.3
|
||||
with:
|
||||
packages: libgtk-3-dev webkit2gtk-4.1 libappindicator3-dev librsvg2-dev patchelf
|
||||
# Increment to invalidate the cache
|
||||
|
||||
20
.github/workflows/gradle.yaml
vendored
20
.github/workflows/gradle.yaml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
bundle-android:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -154,17 +154,17 @@ jobs:
|
||||
env:
|
||||
BUILD_ARCH: ${{ endsWith(matrix.os, 'arm') && 'aarch64' || 'amd64' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: 'SlimeVR-Server'
|
||||
path: server/desktop/build/libs/
|
||||
|
||||
- name: Set up Linux dependencies
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.5.0
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.5.3
|
||||
with:
|
||||
packages: |
|
||||
build-essential curl wget file libssl-dev libgtk-3-dev libappindicator3-dev librsvg2-dev
|
||||
@@ -252,11 +252,11 @@ jobs:
|
||||
needs: [build, test]
|
||||
if: contains(fromJSON('["workflow_dispatch", "create"]'), github.event_name)
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: 'SlimeVR-Server'
|
||||
path: server/desktop/build/libs/
|
||||
@@ -332,11 +332,11 @@ jobs:
|
||||
env:
|
||||
BUILD_ARCH: ${{ endsWith(matrix.os, 'arm') && 'win-aarch64' || 'win64' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: 'SlimeVR-Server'
|
||||
path: server/desktop/build/libs/
|
||||
|
||||
2
.github/workflows/pontoon-pr.yml
vendored
2
.github/workflows/pontoon-pr.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: repo-sync/pull-request@v2
|
||||
|
||||
2
.github/workflows/rebase.yml
vendored
2
.github/workflows/rebase.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
ref: pontoon
|
||||
submodules: recursive
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -36,6 +36,8 @@ build/
|
||||
|
||||
# Rust build artifacts
|
||||
/target
|
||||
/.tauri
|
||||
/tauri.settings.gradle
|
||||
|
||||
# direnv has been claimed for Nix usage
|
||||
.direnv/
|
||||
@@ -43,6 +45,8 @@ build/
|
||||
|
||||
# Ignore Android local properties
|
||||
local.properties
|
||||
keystore.properties
|
||||
/.android
|
||||
|
||||
# Ignore temporary config
|
||||
vrconfig.yml.tmp
|
||||
|
||||
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -2645,7 +2645,7 @@ version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
||||
dependencies = [
|
||||
"proc-macro-crate 1.3.1",
|
||||
"proc-macro-crate 2.0.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
@@ -4081,7 +4081,6 @@ name = "slimevr"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
"color-eyre",
|
||||
@@ -4539,9 +4538,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c341290d31991dbca38b31d412c73dfbdb070bb11536784f19dd2211d13b778f"
|
||||
checksum = "8c6ef84ee2f2094ce093e55106d90d763ba343fad57566992962e8f76d113f99"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"dunce",
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
plugins {
|
||||
id("org.ajoberstar.grgit")
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:8.6.1")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.properties["kotlinVersion"]}")
|
||||
}
|
||||
}
|
||||
|
||||
subprojects.filter { it.name.contains("tauri") }.forEach {
|
||||
it.repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
23
buildSrc/build.gradle.kts
Normal file
23
buildSrc/build.gradle.kts
Normal file
@@ -0,0 +1,23 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("pluginsForCoolKids") {
|
||||
id = "rust"
|
||||
implementationClass = "RustPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(gradleApi())
|
||||
implementation("com.android.tools.build:gradle:8.6.1")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import java.io.File
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
open class BuildTask : DefaultTask() {
|
||||
@Input
|
||||
var rootDirRel: String? = null
|
||||
@Input
|
||||
var target: String? = null
|
||||
@Input
|
||||
var release: Boolean? = null
|
||||
|
||||
@TaskAction
|
||||
fun assemble() {
|
||||
val executable = """pnpm""";
|
||||
try {
|
||||
runTauriCli(executable)
|
||||
} catch (e: Exception) {
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
runTauriCli("$executable.cmd")
|
||||
} else if (Os.isFamily(Os.FAMILY_UNIX)){
|
||||
runTauriCli("/nix/store/r2n3dbbp0djly6wjxx43sbffaq3abjpy-pnpm-10.15.0/bin/pnpm")
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runTauriCli(executable: String) {
|
||||
val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
|
||||
val target = target ?: throw GradleException("target cannot be null")
|
||||
val release = release ?: throw GradleException("release cannot be null")
|
||||
val args = listOf("tauri", "android", "android-studio-script")
|
||||
|
||||
project.exec {
|
||||
workingDir(File(project.projectDir, rootDirRel))
|
||||
executable(executable)
|
||||
args(args)
|
||||
if (project.logger.isEnabled(LogLevel.DEBUG)) {
|
||||
args("-vv")
|
||||
} else if (project.logger.isEnabled(LogLevel.INFO)) {
|
||||
args("-v")
|
||||
}
|
||||
if (release) {
|
||||
args("--release")
|
||||
}
|
||||
args(listOf("--target", target))
|
||||
}.assertNormalExitValue()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import com.android.build.api.dsl.ApplicationExtension
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.get
|
||||
|
||||
const val TASK_GROUP = "rust"
|
||||
|
||||
open class Config {
|
||||
lateinit var rootDirRel: String
|
||||
}
|
||||
|
||||
open class RustPlugin : Plugin<Project> {
|
||||
private lateinit var config: Config
|
||||
|
||||
override fun apply(project: Project) = with(project) {
|
||||
config = extensions.create("rust", Config::class.java)
|
||||
|
||||
val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64");
|
||||
val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList
|
||||
|
||||
val defaultArchList = listOf("arm64", "arm", "x86", "x86_64");
|
||||
val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList
|
||||
|
||||
val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64")
|
||||
|
||||
extensions.configure<ApplicationExtension> {
|
||||
@Suppress("UnstableApiUsage")
|
||||
flavorDimensions.add("abi")
|
||||
productFlavors {
|
||||
create("universal") {
|
||||
dimension = "abi"
|
||||
ndk {
|
||||
abiFilters += abiList
|
||||
}
|
||||
}
|
||||
defaultArchList.forEachIndexed { index, arch ->
|
||||
create(arch) {
|
||||
dimension = "abi"
|
||||
ndk {
|
||||
abiFilters.add(defaultAbiList[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
for (profile in listOf("debug", "release")) {
|
||||
val profileCapitalized = profile.replaceFirstChar { it.uppercase() }
|
||||
val buildTask = tasks.maybeCreate(
|
||||
"rustBuildUniversal$profileCapitalized",
|
||||
DefaultTask::class.java
|
||||
).apply {
|
||||
group = TASK_GROUP
|
||||
description = "Build dynamic library in $profile mode for all targets"
|
||||
}
|
||||
|
||||
tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask)
|
||||
|
||||
for (targetPair in targetsList.withIndex()) {
|
||||
val targetName = targetPair.value
|
||||
val targetArch = archList[targetPair.index]
|
||||
val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() }
|
||||
val targetBuildTask = project.tasks.maybeCreate(
|
||||
"rustBuild$targetArchCapitalized$profileCapitalized",
|
||||
BuildTask::class.java
|
||||
).apply {
|
||||
group = TASK_GROUP
|
||||
description = "Build dynamic library in $profile mode for $targetArch"
|
||||
rootDirRel = config.rootDirRel
|
||||
target = targetName
|
||||
release = profile == "release"
|
||||
}
|
||||
|
||||
buildTask.dependsOn(targetBuildTask)
|
||||
tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn(
|
||||
targetBuildTask
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
flake.nix
41
flake.nix
@@ -57,11 +57,36 @@
|
||||
_module.args.pkgs = import self.inputs.nixpkgs {
|
||||
inherit system;
|
||||
overlays = [nixgl.overlay];
|
||||
# Allow android SDK
|
||||
# config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||
# "android-sdk-cmdline-tools"
|
||||
# "android-sdk-platform-tools"
|
||||
# "platform-tools"
|
||||
# "android-sdk-tools"
|
||||
# "android-sdk-emulator"
|
||||
# "android-sdk-system-image-32-google_apis_playstore-arm64-v8a-system-image-32-google_apis_playstore-x86_64"
|
||||
# "system-image-32-google_apis_playstore-arm64-v8a"
|
||||
# "system-image-32-google_apis_playstore-x86_64"
|
||||
# "android-sdk-system-image-34-google_apis_playstore-arm64-v8a-system-image-34-google_apis_playstore-x86_64"
|
||||
# "system-image-34-google_apis_playstore-arm64-v8a"
|
||||
# "system-image-34-google_apis_playstore-x86_64"
|
||||
# "emulator"
|
||||
# "tools"
|
||||
# "android-sdk-build-tools"
|
||||
# "build-tools"
|
||||
# "android-sdk-platforms"
|
||||
# "platforms"
|
||||
# "cmake"
|
||||
# "android-sdk-ndk"
|
||||
# "ndk"
|
||||
# "android-sdk-extras-google-gcm"
|
||||
# "extras-google-gcm"
|
||||
# "cmdline-tools"
|
||||
# ];
|
||||
};
|
||||
|
||||
devenv.shells.default = let
|
||||
fenixpkgs = inputs'.fenix.packages;
|
||||
rust_toolchain = lib.importTOML ./rust-toolchain.toml;
|
||||
in {
|
||||
name = "slimevr";
|
||||
|
||||
@@ -76,6 +101,7 @@
|
||||
(with pkgs; [
|
||||
pkgs.nixgl.nixGLIntel
|
||||
cacert
|
||||
stow
|
||||
])
|
||||
++ lib.optionals pkgs.stdenv.isLinux (with pkgs; [
|
||||
atk
|
||||
@@ -118,6 +144,12 @@
|
||||
};
|
||||
languages.kotlin.enable = true;
|
||||
|
||||
# android = {
|
||||
# enable = true;
|
||||
# googleAPIs.enable = false;
|
||||
# googleTVAddOns.enable = false;
|
||||
# };
|
||||
|
||||
languages.javascript = {
|
||||
enable = true;
|
||||
corepack.enable = true;
|
||||
@@ -127,11 +159,10 @@
|
||||
|
||||
languages.rust = {
|
||||
enable = true;
|
||||
toolchain = fenixpkgs.fromToolchainName {
|
||||
name = rust_toolchain.toolchain.channel;
|
||||
sha256 = "sha256-yMuSb5eQPO/bHv+Bcf/US8LVMbf/G/0MSfiPwBhiPpk=";
|
||||
toolchainPackage = fenixpkgs.fromToolchainFile {
|
||||
file = ./rust-toolchain.toml;
|
||||
sha256 = "sha256-+9FmLhAOezBZCOziO0Qct1NOrfpjNsXxc/8I0c7BdKE=";
|
||||
};
|
||||
components = rust_toolchain.toolchain.components;
|
||||
};
|
||||
|
||||
env = {
|
||||
|
||||
@@ -3,14 +3,26 @@ org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAME
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
|
||||
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
|
||||
-Dfile.encoding=UTF-8
|
||||
|
||||
kotlin.code.style=official
|
||||
# https://github.com/Kotlin/kotlinx-atomicfu#atomicfu-compiler-plugin
|
||||
kotlinx.atomicfu.enableJvmIrTransformation=true
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app"s APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonFinalResIds=false
|
||||
org.gradle.unsafe.configuration-cache=false
|
||||
|
||||
kotlinVersion=2.0.20
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"@tanstack/react-query": "^5.48.0",
|
||||
"@tauri-apps/api": "^2.0.2",
|
||||
"@tauri-apps/plugin-dialog": "^2.0.0",
|
||||
"@tauri-apps/plugin-fs": "^2.0.0",
|
||||
"@tauri-apps/plugin-fs": "2.4.1",
|
||||
"@tauri-apps/plugin-http": "^2.5.0",
|
||||
"@tauri-apps/plugin-os": "^2.0.0",
|
||||
"@tauri-apps/plugin-shell": "^2.0.0",
|
||||
|
||||
@@ -237,6 +237,8 @@ reset-reset_all_warning_default-v2 =
|
||||
|
||||
reset-full = Full Reset
|
||||
reset-mounting = Reset Mounting
|
||||
reset-mounting-feet = Reset Feet Mounting
|
||||
reset-mounting-fingers = Reset Fingers Mounting
|
||||
reset-yaw = Yaw Reset
|
||||
|
||||
## Serial detection stuff
|
||||
@@ -274,7 +276,7 @@ widget-overlay-is_mirrored_label = Display Overlay as Mirror
|
||||
widget-drift_compensation-clear = Clear drift compensation
|
||||
|
||||
## Widget: Clear Reset Mounting
|
||||
widget-clear_mounting = Clear reset mounting
|
||||
widget-clear_mounting = Clear Reset Mounting
|
||||
|
||||
## Widget: Developer settings
|
||||
widget-developer_mode = Developer Mode
|
||||
@@ -584,8 +586,8 @@ settings-general-fk_settings-leg_tweak-floor_clip-description = Floor-clip can r
|
||||
settings-general-fk_settings-leg_tweak-toe_snap-description = Toe-snap attempts to guess the rotation of your feet if foot trackers are not in use.
|
||||
settings-general-fk_settings-leg_tweak-foot_plant-description = Foot-plant rotates your feet to be parallel to the ground when in contact.
|
||||
settings-general-fk_settings-leg_fk = Leg tracking
|
||||
settings-general-fk_settings-leg_fk-reset_mounting_feet-description = Enable feet Mounting Reset by tiptoeing.
|
||||
settings-general-fk_settings-leg_fk-reset_mounting_feet = Feet Mounting Reset
|
||||
settings-general-fk_settings-leg_fk-reset_mounting_feet-description-v1 = Force feet mounting reset during general mounting resets.
|
||||
settings-general-fk_settings-leg_fk-reset_mounting_feet-v1 = Force feet mounting reset
|
||||
settings-general-fk_settings-enforce_joint_constraints = Skeletal Limits
|
||||
settings-general-fk_settings-enforce_joint_constraints-enforce_constraints = Enforce constraints
|
||||
settings-general-fk_settings-enforce_joint_constraints-enforce_constraints-description = Prevents joints from rotating past their limit
|
||||
|
||||
@@ -269,6 +269,7 @@ navbar-settings = Réglages
|
||||
|
||||
bvh-start_recording = Enregistrer BVH
|
||||
bvh-recording = Enregistrement...
|
||||
bvh-save_title = Sauvegarder l’enregistrement BVH
|
||||
|
||||
## Tracking pause
|
||||
|
||||
@@ -406,6 +407,7 @@ tracker-settings-forget-label = Oublier capteur
|
||||
tracker-settings-update-unavailable = Ne peut pas être mis à jour (DIY)
|
||||
tracker-settings-update-low-battery = Mise à jour impossible. Batterie inférieure à 50 %
|
||||
tracker-settings-update-up_to_date = À jour
|
||||
tracker-settings-update-blocked = Mise à jour non disponible. Aucune autre version disponible
|
||||
tracker-settings-update-available = { $versionName } est maintenant disponible
|
||||
tracker-settings-update = Mettre à jour maintenant
|
||||
tracker-settings-update-title = Version du micrologiciel
|
||||
@@ -584,6 +586,7 @@ settings-stay_aligned-relaxed_poses-sitting = Ajuster les capteurs en position a
|
||||
settings-stay_aligned-relaxed_poses-flat = Ajuster les capteurs en position assise sur le sol ou allongée sur le dos
|
||||
settings-stay_aligned-relaxed_poses-save_pose = Enregistrer la posture
|
||||
settings-stay_aligned-relaxed_poses-reset_pose = Réinitialiser la posture
|
||||
settings-stay_aligned-relaxed_poses-close = Fermer
|
||||
settings-stay_aligned-debug-label = Débogage
|
||||
settings-stay_aligned-debug-description = Veuillez inclure vos paramètres lorsque vous signalez des problèmes concernant Garder Aligné.
|
||||
settings-stay_aligned-debug-copy-label = Copier les paramètres dans le presse-papiers
|
||||
@@ -744,6 +747,9 @@ settings-interface-behavior-error_tracking-description_v2 =
|
||||
|
||||
Pour offrir la meilleure expérience utilisateur possible, nous collectons des rapports d'erreurs anonymisés, des mesures de performance et des informations sur le système d'exploitation. Cela nous aide à détecter les bugs et les problèmes liés à SlimeVR. Ces données sont collectées via Sentry.io.
|
||||
settings-interface-behavior-error_tracking-label = Envoyer les erreurs aux développeurs
|
||||
settings-interface-behavior-bvh_directory = Répertoire pour sauvegarder les enregistrements BVH
|
||||
settings-interface-behavior-bvh_directory-description = Choisissez un répertoire où sauvegarder vos enregistrements BVH au lieu d’avoir à choisir où les sauvegarder à chaque fois.
|
||||
settings-interface-behavior-bvh_directory-label = Répertoire où sauvegarder les enregistrements BVH
|
||||
|
||||
## Serial settings
|
||||
|
||||
@@ -1014,7 +1020,7 @@ onboarding-connect_tracker-next = J'ai connecté tous mes capteurs
|
||||
|
||||
onboarding-calibration_tutorial = Tutoriel de calibration IMU
|
||||
onboarding-calibration_tutorial-subtitle = Ceci vous aidera à réduire la dérive du capteur !
|
||||
onboarding-calibration_tutorial-description = Chaque fois que vous allumez vos capteurs, ils doivent rester sur une surface plane pour se calibrer. Faisons de même en cliquant sur le bouton « { onboarding-calibration_tutorial-calibrate } ». <b>Ne les déplacez pas !</b>
|
||||
onboarding-calibration_tutorial-description-v1 = Après avoir allumé vos capteurs, placez-les sur une surface stable pendant un moment pour leur permettre de se calibrer. La calibration peut être effectué n'importe quand lors que les capteurs sont allumés - cette page sert simplement de tutoriel. Pour commencer, cliquez sur le bouton « { onboarding-calibration_tutorial-calibrate } », puis <b>ne déplacez pas vos capteurs !</b>
|
||||
onboarding-calibration_tutorial-calibrate = J'ai posé mes capteurs sur la table
|
||||
onboarding-calibration_tutorial-status-waiting = En attente de vous
|
||||
onboarding-calibration_tutorial-status-calibrating = Calibration...
|
||||
@@ -1332,13 +1338,13 @@ onboarding-stay_aligned-preparation-title = Préparation
|
||||
onboarding-stay_aligned-preparation-tip = Assurez-vous de vous tenir droit. Vous devez regarder vers l'avant et vos bras doivent être le long de votre corps.
|
||||
onboarding-stay_aligned-relaxed_poses-standing-title = Posture debout détendu
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-0 = 1. Tenez-vous dans une position confortable. Détendez-vous !
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-2 = 3. Appuyez sur le bouton « Enregistrer la posture ».
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-1-v2 = 2. Appuyez sur le bouton « Enregistrer la posture ».
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-title = Posture assis détendu dans une chaise
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-0 = 1. Asseyez-vous dans une position confortable. Détendez-vous !
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-2 = 3. Appuyez sur le bouton « Enregistrer la posture ».
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-1-v2 = 2. Appuyez sur le bouton « Enregistrer la posture ».
|
||||
onboarding-stay_aligned-relaxed_poses-flat-title = Posture assis détendu sur le sol
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-0 = 1. Asseyez-vous sur le sol, les jambes devant. Détendez-vous !
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-2 = 3. Appuyez sur le bouton « Enregistrer la posture ».
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-1-v2 = 2. Appuyez sur le bouton « Enregistrer la posture ».
|
||||
onboarding-stay_aligned-relaxed_poses-skip_step = Sauter
|
||||
onboarding-stay_aligned-done-title = Garder Aligné activé !
|
||||
onboarding-stay_aligned-done-description = La configuration de Garder Aligné est terminée !
|
||||
|
||||
@@ -111,29 +111,122 @@ board_type-GLOVE_IMU_SLIMEVR_DEV = SlimeVR Dev IMU Handschoen
|
||||
|
||||
skeleton_bone-NONE = Geen
|
||||
skeleton_bone-HEAD = Hoofdverschuiving
|
||||
skeleton_bone-HEAD-desc =
|
||||
Dit is de afstand tussen je headset en het midden van je hoofd.
|
||||
Om dit aan te passen, schud je je hoofd naar links en rechts alsof je 'nee' zegt,
|
||||
pas het aan totdat beweging van de andere trackers te verwaarlozen is.
|
||||
skeleton_bone-NECK = Neklengte
|
||||
skeleton_bone-NECK-desc =
|
||||
Dit is de afstand tussen het midden van je hoofd en de basis van je nek.
|
||||
Om dit aan te passen, beweeg je je hoofd op en neer alsof je knikt, of kantel je je hoofd
|
||||
naar links en rechts. Wijzig de positie totdat beweging in andere trackers verwaarloosbaar is.
|
||||
skeleton_bone-torso_group = Romp lengte
|
||||
skeleton_bone-torso_group-desc =
|
||||
Dit is de afstand van je nek tot je heupen.
|
||||
Om dit aan te passen, ga rechtop staan en pas het aan totdat je virtuele heupen
|
||||
in lijn zijn met je echte heupen.
|
||||
skeleton_bone-UPPER_CHEST = Bovenborst Lengte
|
||||
skeleton_bone-UPPER_CHEST-desc =
|
||||
Dit is de afstand tussen de basis van je nek en het midden van je borst.
|
||||
Om dit aan te passen, stel je de torso-lengte correct af en pas je deze aan in verschillende houdingen
|
||||
(zitten, bukken, liggen, enz.) totdat je virtuele ruggengraat overeenkomt met je echte.
|
||||
skeleton_bone-CHEST_OFFSET = Borstoffset
|
||||
skeleton_bone-CHEST_OFFSET-desc =
|
||||
Dit kan worden aangepast om je virtuele borsttracker omhoog of omlaag te verplaatsen,
|
||||
om te helpen bij de kalibratie in bepaalde spellen of applicaties die verwachten dat deze hoger of lager staat.
|
||||
skeleton_bone-CHEST = Borstafstand
|
||||
skeleton_bone-CHEST-desc =
|
||||
Dit is de afstand van het midden van je borst tot het midden van je ruggengraat.
|
||||
Om dit aan te passen, stel je de torso-lengte correct af en pas je deze aan in verschillende houdingen
|
||||
(zitten, bukken, liggen, enz.) totdat je virtuele ruggengraat overeenkomt met je echte.
|
||||
skeleton_bone-WAIST = Taille lengte
|
||||
skeleton_bone-WAIST-desc =
|
||||
Dit is de afstand van het midden van je ruggengraat tot je navel.
|
||||
Om dit aan te passen, stel je de torso-lengte correct af en pas je deze aan in verschillende houdingen
|
||||
(zitten, bukken, liggen, enz.) totdat je virtuele ruggengraat overeenkomt met je echte.
|
||||
skeleton_bone-HIP = Heuplengte
|
||||
skeleton_bone-HIP-desc =
|
||||
Dit is de afstand van je navel tot je heupen.
|
||||
Om dit aan te passen, stel je de torso-lengte correct in en pas je deze aan in verschillende houdingen
|
||||
(zitten, bukken, liggen, enz.) totdat je virtuele ruggengraat overeenkomt met je echte.
|
||||
skeleton_bone-HIP_OFFSET = Heupoffset
|
||||
skeleton_bone-HIP_OFFSET-desc =
|
||||
Dit kan worden aangepast om je virtuele heuptracker omhoog of omlaag te verplaatsen,
|
||||
om te helpen bij de kalibratie in bepaalde spellen of applicaties die mogelijk verwachten dat deze zich rond je middel bevindt.
|
||||
skeleton_bone-HIPS_WIDTH = Heupbreedte
|
||||
skeleton_bone-HIPS_WIDTH-desc =
|
||||
Dit is de afstand tussen het begin van je benen.
|
||||
Om dit aan te passen, voer je een volledige reset uit met je benen gestrekt en pas je het aan totdat je virtuele benen horizontaal overeenkomen met je echte.
|
||||
skeleton_bone-leg_group = Beenlengte
|
||||
skeleton_bone-leg_group-desc =
|
||||
Dit is de afstand van je heupen tot je voeten.
|
||||
Om dit aan te passen, pas je je torso-lengte op de juiste manier aan
|
||||
totdat je virtuele voeten op hetzelfde niveau staan als je echte.
|
||||
skeleton_bone-UPPER_LEG = Bovenbeenlengte
|
||||
skeleton_bone-UPPER_LEG-desc =
|
||||
Dit is de afstand van je heupen tot je knieën.
|
||||
Om dit aan te passen, pas je je beenlengte op de juiste manier aan
|
||||
totdat je virtuele knieën op dezelfde hoogte zijn als je echte.
|
||||
skeleton_bone-LOWER_LEG = Onderbeenlengte
|
||||
skeleton_bone-LOWER_LEG-desc =
|
||||
Dit is de afstand van je knieën tot je enkels.
|
||||
Om dit aan te passen, pas je je beenlengte op de juiste manier aan
|
||||
totdat je virtuele knieën op dezelfde hoogte zijn als je echte knieën.
|
||||
skeleton_bone-FOOT_LENGTH = Voetlengte
|
||||
skeleton_bone-FOOT_LENGTH-desc =
|
||||
Dit is de afstand van je enkels tot je tenen.
|
||||
Om dit aan te passen, ga op je tenen staan en pas het aan totdat je virtuele voeten op hun plaats blijven.
|
||||
skeleton_bone-FOOT_SHIFT = Voetverschuiving
|
||||
skeleton_bone-FOOT_SHIFT-desc =
|
||||
Deze waarde is de horizontale afstand van je knie tot je enkel.
|
||||
Dit houdt rekening met het feit dat je onderbenen naar achteren staan wanneer je rechtop staat.
|
||||
Om dit aan te passen, stel je de voetlengte in op 0, voer je een volledige reset uit,
|
||||
en pas je het aan totdat je virtuele voeten op één lijn liggen met het midden van je enkels.
|
||||
skeleton_bone-SKELETON_OFFSET = Skelet offset
|
||||
skeleton_bone-SKELETON_OFFSET-desc =
|
||||
Dit kan worden aangepast om al je trackers naar voren of naar achteren te verschuiven.
|
||||
Het kan worden gebruikt om te helpen bij de kalibratie in bepaalde spellen of toepassingen
|
||||
die mogelijk verwachten dat je trackers verder naar voren staan.
|
||||
skeleton_bone-SHOULDERS_DISTANCE = Schoudersafstand
|
||||
skeleton_bone-SHOULDERS_DISTANCE-desc =
|
||||
Dit is de verticale afstand van de basis van je nek tot je schouders.
|
||||
Om dit aan te passen, stel je de lengte van je bovenarm in op 0 en
|
||||
pas je deze aan totdat je virtuele elleboogtrackers verticaal uitlijnen met je echte schouders.
|
||||
skeleton_bone-SHOULDERS_WIDTH = Schouderbreedte
|
||||
skeleton_bone-SHOULDERS_WIDTH-desc =
|
||||
Dit is de horizontale afstand van de basis van je nek tot je schouders.
|
||||
Om dit aan te passen, stel je de lengte van je bovenarm in op 0 en pas je deze aan
|
||||
totdat je virtuele elleboogtrackers horizontaal uitlijnen met je echte schouders.
|
||||
skeleton_bone-arm_group = Armlengte
|
||||
skeleton_bone-arm_group-desc =
|
||||
Dit is de afstand van je schouders tot je polsen.
|
||||
Om dit aan te passen, pas je de schouderafstand correct aan, stel je Handafstand Y in op 0,
|
||||
en pas je deze aan totdat je handtrackers op één lijn liggen met je polsen.
|
||||
skeleton_bone-UPPER_ARM = Bovenarmlengte
|
||||
skeleton_bone-UPPER_ARM-desc =
|
||||
Dit is de afstand van je schouders tot je ellebogen.
|
||||
Om dit aan te passen, pas je de armlengte correct aan en pas je deze aan
|
||||
totdat je elleboogtrackers overeenkomen met je echte ellebogen.
|
||||
skeleton_bone-LOWER_ARM = Onderarmlengte
|
||||
skeleton_bone-LOWER_ARM-desc =
|
||||
Dit is de afstand van je ellebogen tot je polsen.
|
||||
Om dit aan te passen, pas je de armlengte correct aan en pas je deze aan
|
||||
totdat je elleboogtrackers overeenkomen met je echte ellebogen.
|
||||
skeleton_bone-HAND_Y = Afstand hand Y
|
||||
skeleton_bone-HAND_Y-desc =
|
||||
Dit is de verticale afstand van je polsen tot het midden van je hand.
|
||||
Om dit aan te passen voor motion capture, pas je de armlengte correct aan
|
||||
en pas je deze aan totdat je handtrackers verticaal uitgelijnd zijn met het midden van je handen.
|
||||
Wil je het aanpassen voor elleboogtracking vanaf je controllers,
|
||||
stel dan de armlengte in op 0 en pas je deze aan totdat je elleboogtrackers verticaal op één lijn liggen met je polsen.
|
||||
skeleton_bone-HAND_Z = Afstand hand Z
|
||||
skeleton_bone-HAND_Z-desc =
|
||||
Dit is de horizontale afstand van je polsen tot het midden van je hand.
|
||||
Als je dit wilt aanpassen voor motion capture, stel je deze in op 0.
|
||||
Wil je het aanpassen voor elleboogtracking vanaf je controllers, stel dan de armlengte in op 0
|
||||
en pas je deze aan totdat je elleboogtrackers horizontaal op één lijn liggen met je polsen.
|
||||
skeleton_bone-ELBOW_OFFSET = Elleboogoffset
|
||||
skeleton_bone-ELBOW_OFFSET-desc = Dit kan worden aangepast om je virtuele elleboogtrackers omhoog of omlaag te verplaatsen, zodat wordt voorkomen dat VRChat per ongeluk een elleboogtracker aan de borst koppelt.
|
||||
|
||||
## Tracker reset buttons
|
||||
|
||||
@@ -148,6 +241,8 @@ reset-reset_all_warning_default-v2 =
|
||||
Weet je zeker dat je dit wilt doen?
|
||||
reset-full = Volledige reset
|
||||
reset-mounting = Reset montage
|
||||
reset-mounting-feet = Reset voetmontage
|
||||
reset-mounting-fingers = Reset vingermontage
|
||||
reset-yaw = Yaw Reset
|
||||
|
||||
## Serial detection stuff
|
||||
@@ -173,6 +268,7 @@ navbar-settings = Instellingen
|
||||
|
||||
bvh-start_recording = BVH opnemen
|
||||
bvh-recording = Opname bezig...
|
||||
bvh-save_title = Sla BVH-opname op
|
||||
|
||||
## Tracking pause
|
||||
|
||||
@@ -213,6 +309,7 @@ widget-imu_visualizer-rotation_raw = Rauw
|
||||
widget-imu_visualizer-rotation_preview = Preview
|
||||
widget-imu_visualizer-acceleration = Versnelling
|
||||
widget-imu_visualizer-position = Positie
|
||||
widget-imu_visualizer-stay_aligned = Blijf in lijn
|
||||
|
||||
## Widget: Skeleton Visualizer
|
||||
|
||||
@@ -240,6 +337,7 @@ tracker-table-column-temperature = Temp. °C
|
||||
tracker-table-column-linear-acceleration = Accel. X/Y/Z
|
||||
tracker-table-column-rotation = Rotatie X/Y/Z
|
||||
tracker-table-column-position = Positie X/Y/Z
|
||||
tracker-table-column-stay_aligned = Blijf in lijn
|
||||
tracker-table-column-url = URL
|
||||
|
||||
## Tracker rotation
|
||||
@@ -305,7 +403,9 @@ tracker-settings-forget = Vergeet tracker
|
||||
tracker-settings-forget-description = Verwijdert de tracker van de SlimeVR Server en voorkomt dat deze verbinding kan maken totdat de server opnieuw wordt opgestart. De configuratie van de tracker blijft behouden.
|
||||
tracker-settings-forget-label = Vergeet tracker
|
||||
tracker-settings-update-unavailable = Kan niet worden bijgewerkt (DIY)
|
||||
tracker-settings-update-low-battery = Kan niet worden bijgewerkt. Batterij lager dan 50%
|
||||
tracker-settings-update-up_to_date = Up to date.
|
||||
tracker-settings-update-blocked = Update is niet beschikbaar. Er zijn geen andere versies beschikbaar.
|
||||
tracker-settings-update-available = { $versionName } is nu beschikbaar
|
||||
tracker-settings-update = Werk nu bij.
|
||||
tracker-settings-update-title = Firmware versie
|
||||
@@ -375,6 +475,7 @@ mounting_selection_menu-close = Sluiten
|
||||
settings-sidebar-title = Instellingen
|
||||
settings-sidebar-general = Algemeen
|
||||
settings-sidebar-tracker_mechanics = Trackersinstellingen
|
||||
settings-sidebar-stay_aligned = Blijf in lijn
|
||||
settings-sidebar-fk_settings = FK-instellingen
|
||||
settings-sidebar-gesture_control = Tikbediening
|
||||
settings-sidebar-interface = Interface
|
||||
@@ -386,6 +487,7 @@ settings-sidebar-appearance = Uiterlijk
|
||||
settings-sidebar-notifications = Notificaties
|
||||
settings-sidebar-behavior = Gedrag
|
||||
settings-sidebar-firmware-tool = DIY Firmware Tool
|
||||
settings-sidebar-vrc_warnings = VRChat Configuratie-waarschuwingen
|
||||
settings-sidebar-advanced = Geavanceerd
|
||||
|
||||
## SteamVR settings
|
||||
@@ -443,7 +545,7 @@ settings-general-tracker_mechanics-drift_compensation-prediction = Voorspelling
|
||||
# This cares about multilines
|
||||
settings-general-tracker_mechanics-drift_compensation-prediction-description =
|
||||
Voorspelt compensatie van gierdrift buiten het eerder gemeten bereik.
|
||||
Schakel dit in als uw trackers continu om de gier-as draaien.
|
||||
Schakel dit in als jouw trackers continu om de gier-as draaien.
|
||||
settings-general-tracker_mechanics-drift_compensation-prediction-label = Voorspelling van driftcompensatie
|
||||
settings-general-tracker_mechanics-drift_compensation_warning =
|
||||
<b>Waarschuwing:</b> Gebruik alleen driftcompensatie als je heel vaak
|
||||
@@ -463,6 +565,25 @@ settings-general-tracker_mechanics-use_mag_on_all_trackers-description =
|
||||
Gebruikt magnetometer op alle trackers die er een compatibele firmware voor hebben, waardoor drift in stabiele magnetische omgevingen wordt verminderd.
|
||||
Je kan dit per individuele tracker uit zetten in de instellingen van de tracker. <b>Sluit geen van de trackers af terwijl u dit in- en uitschakelt!</b>
|
||||
settings-general-tracker_mechanics-use_mag_on_all_trackers-label = Gebruik magnetometer op de trackers
|
||||
settings-stay_aligned = Blijf in lijn
|
||||
settings-stay_aligned-description = ijf in lijn vermindert drift door je trackers geleidelijk aan te passen zodat ze overeenkomen met je ontspannen houdingen.
|
||||
settings-stay_aligned-setup-label = Blijf in lijn instellen
|
||||
settings-stay_aligned-setup-description = Je moet "Blijf in lijn instellen" voltooien om Blijf in lijn te activeren.
|
||||
settings-stay_aligned-warnings-drift_compensation = ⚠ Schakel Drift Compensation uit! Drift Compensation conflicteert met Blijf in lijn.
|
||||
settings-stay_aligned-enabled-label = Trackers aanpassen
|
||||
settings-stay_aligned-hide_yaw_correction-label = Aanpassing verbergen (om te vergelijken zonder Blijf in lijn)
|
||||
settings-stay_aligned-general-label = Algemeen
|
||||
settings-stay_aligned-relaxed_poses-label = Ontspannen houdingen
|
||||
settings-stay_aligned-relaxed_poses-description = Blijf in lijn gebruikt je ontspannen houdingen om je trackers in lijn te houden. Gebruik "Stel Blijf in lijn in" om deze houdingen bij te werken.
|
||||
settings-stay_aligned-relaxed_poses-standing = Pas trackers aan terwijl je staat
|
||||
settings-stay_aligned-relaxed_poses-sitting = Pas trackers aan terwijl je op een stoel zit
|
||||
settings-stay_aligned-relaxed_poses-flat = Pas trackers aan terwijl je op de grond zit of op je rug ligt.
|
||||
settings-stay_aligned-relaxed_poses-save_pose = Sla houding op
|
||||
settings-stay_aligned-relaxed_poses-reset_pose = Reset houding
|
||||
settings-stay_aligned-relaxed_poses-close = Sluiten
|
||||
settings-stay_aligned-debug-label = Foutopsporing
|
||||
settings-stay_aligned-debug-description = Voeg je instellingen toe wanneer je problemen met Blijf in lijn rapporteert.
|
||||
settings-stay_aligned-debug-copy-label = Instellingen naar klembord kopiëren
|
||||
|
||||
## FK/Tracking settings
|
||||
|
||||
@@ -622,6 +743,9 @@ settings-interface-behavior-error_tracking-description_v2 =
|
||||
|
||||
Om de beste gebruikerservaring te bieden, verzamelen we geanonimiseerde foutrapporten, prestatiestatistieken en informatie over het besturingssysteem. Dit helpt ons bij het detecteren van fouten en problemen met SlimeVR. Deze statistieken worden verzameld via Sentry.io.
|
||||
settings-interface-behavior-error_tracking-label = Stuur fouten naar de ontwikkelaars
|
||||
settings-interface-behavior-bvh_directory = Map om BVH-opnames op te slaan
|
||||
settings-interface-behavior-bvh_directory-description = Kies een map om je BVH-opnames op te slaan, zodat je niet elke keer hoeft te kiezen waar je ze opslaat.
|
||||
settings-interface-behavior-bvh_directory-label = Map voor BVH-opnames
|
||||
|
||||
## Serial settings
|
||||
|
||||
@@ -861,6 +985,17 @@ onboarding-connect_tracker-connection_status-looking_for_server = Op zoek naar s
|
||||
onboarding-connect_tracker-connection_status-connection_error = Kan geen verbinding maken met Wi-Fi
|
||||
onboarding-connect_tracker-connection_status-could_not_find_server = Kan de server niet vinden
|
||||
onboarding-connect_tracker-connection_status-done = Verbonden met de server
|
||||
onboarding-connect_tracker-connection_status-no_serial_log = Kon geen logbestanden van de tracker ophalen.
|
||||
onboarding-connect_tracker-connection_status-no_serial_device_found = Kon geen tracker via USB vinden.
|
||||
onboarding-connect_serial-error-modal-no_serial_log = Staat de tracker aan?
|
||||
onboarding-connect_serial-error-modal-no_serial_log-desc = Zorg dat de tracker aan staat en verbonden is met je computer.
|
||||
onboarding-connect_serial-error-modal-no_serial_device_found = Geen trackers gedetecteerd
|
||||
onboarding-connect_serial-error-modal-no_serial_device_found-desc =
|
||||
Sluit een tracker met de meegeleverde USB-kabel aan op je computer en zet de tracker aan.
|
||||
Als dit niet werkt:
|
||||
-probeer een andere USB-kabel
|
||||
-probeer een andere USB-poort
|
||||
-probeer de SlimeVR-server opnieuw te installeren en selecteer "USB Drivers" in het onderdeelkeuze-menu
|
||||
# $amount (Number) - Amount of trackers connected (this is a number, but you can use CLDR plural rules for your language)
|
||||
# More info on https://www.unicode.org/cldr/cldr-aux/charts/22/supplemental/language_plural_rules.html
|
||||
# English in this case only has 2 plural rules, which are "one" and "other",
|
||||
@@ -878,7 +1013,7 @@ onboarding-connect_tracker-next = Ik heb al mijn trackers verbonden
|
||||
|
||||
onboarding-calibration_tutorial = Handleiding voor IMU-kalibratie
|
||||
onboarding-calibration_tutorial-subtitle = Helpt met het verminderen van het driften van de trackers!
|
||||
onboarding-calibration_tutorial-description = Elke keer dat je jouw trackers inschakelt, moeten ze even op een plat oppervlak rusten om te kalibreren. Leg al je trackers op een vlak oppervlak en <b>verplaats ze niet!</b>
|
||||
onboarding-calibration_tutorial-description-v1 = Zet je trackers aan en leg ze even op een stabiele ondergrond om te kalibreren. Kalibratie kan op elk moment na het inschakelen van de trackers worden uitgevoerd — deze pagina biedt alleen een handleiding. Klik op de knop "{ onboarding-calibration_tutorial-calibrate }" om te beginnen en <b>beweeg je trackers daarna niet meer!</b>
|
||||
onboarding-calibration_tutorial-calibrate = Al mijn trackers liggen neer
|
||||
onboarding-calibration_tutorial-status-waiting = Ik wacht op jou
|
||||
onboarding-calibration_tutorial-status-calibrating = Kalibreren
|
||||
@@ -1006,7 +1141,7 @@ onboarding-assign_trackers-warning-WAIST =
|
||||
|
||||
onboarding-choose_mounting = Welke montagekalibratiemethode moet worden gebruikt?
|
||||
# Multiline text
|
||||
onboarding-choose_mounting-description = De oriëntatie van de montage corrigeert de plaatsing van trackers op uw lichaam.
|
||||
onboarding-choose_mounting-description = De oriëntatie van de montage corrigeert de plaatsing van trackers op je lichaam.
|
||||
onboarding-choose_mounting-auto_mounting = Automatische bevestiging
|
||||
# Italicized text
|
||||
onboarding-choose_mounting-auto_mounting-label-v2 = Aanbevolen
|
||||
@@ -1044,6 +1179,9 @@ onboarding-automatic_mounting-mounting_reset-title = Montage-reset
|
||||
onboarding-automatic_mounting-mounting_reset-step-0 = 1. Ga staan in een "skie"-houding met gebogen benen, je bovenlichaam naar voren gekanteld en armen gebogen.
|
||||
onboarding-automatic_mounting-mounting_reset-step-1 = 2. Druk op de knop "Reset montage" en wacht 3 seconden voordat de montagerichtingen van de trackers opnieuw worden ingesteld.
|
||||
onboarding-automatic_mounting-preparation-title = Voorbereiding
|
||||
onboarding-automatic_mounting-preparation-v2-step-0 = 1. Druk op de knop "Volledige reset".
|
||||
onboarding-automatic_mounting-preparation-v2-step-1 = 2. Ga rechtop staan met je armen langs je zij. Zorg dat je recht vooruit kijkt.
|
||||
onboarding-automatic_mounting-preparation-v2-step-2 = 3. Houd deze houding aan totdat de timer van 3 seconden is afgelopen.
|
||||
onboarding-automatic_mounting-put_trackers_on-title = Doe je trackers aan
|
||||
onboarding-automatic_mounting-put_trackers_on-description = Om montagerichtingen te kalibreren gaan we gebruik maken van de trackers die je net hebt toegewezen. Doe al je trackers aan, je kunt zien welke trackers welke zijn in de figuur rechts.
|
||||
onboarding-automatic_mounting-put_trackers_on-next = Ik heb al mijn trackers aan
|
||||
@@ -1057,6 +1195,11 @@ onboarding-manual_proportions-fine_tuning_button-disabled-tooltip = Sluit een VR
|
||||
onboarding-manual_proportions-export = Export proporties
|
||||
onboarding-manual_proportions-import = Importeer proporties
|
||||
onboarding-manual_proportions-file_type = Lichaamsproporties bestand
|
||||
onboarding-manual_proportions-normal_increment = Normale verhoging
|
||||
onboarding-manual_proportions-precise_increment = Nauwkeurige verhoging
|
||||
onboarding-manual_proportions-grouped_proportions = Gegroepeerde verhoudingen
|
||||
onboarding-manual_proportions-all_proportions = Alle verhoudingen
|
||||
onboarding-manual_proportions-estimated_height = Geschatte gebruikerslengte
|
||||
|
||||
## Tracker automatic proportions setup
|
||||
|
||||
@@ -1074,6 +1217,8 @@ onboarding-automatic_proportions-requirements-descriptionv2 = Je hebt voldaan aa
|
||||
onboarding-automatic_proportions-requirements-next = Ik heb de vereisten gelezen
|
||||
onboarding-automatic_proportions-check_height-title-v3 = Meet de hoogte van uw headset
|
||||
onboarding-automatic_proportions-check_height-description-v2 = De hoogte van uw headset (HMD) moet iets minder zijn dan uw volledige lengte, aangezien headsets uw ooghoogte meten. Deze meting wordt gebruikt als basis voor uw lichaamsverhoudingen.
|
||||
# All the text is in bold!
|
||||
onboarding-automatic_proportions-check_height-calculation_warning-v3 = Begin met meten terwijl je <u>rechtop</u> staat om je lengte te meten. Let erop dat je je handen niet hoger dan je headset tilt, want dat kan de meting beïnvloeden!
|
||||
onboarding-automatic_proportions-check_height-guardian_tip = Als je een losse VR-bril gebruikt, zorg er dan voor dat je guardian/veilige zone is ingeschakeld zodat je lengte correct is gekalibreerd!
|
||||
# Context is that the height is unknown
|
||||
onboarding-automatic_proportions-check_height-unknown = Onbekend
|
||||
@@ -1165,6 +1310,37 @@ onboarding-scaled_proportions-done-description = Je lichaamsverhoudingen zouden
|
||||
|
||||
## Stay Aligned setup
|
||||
|
||||
onboarding-stay_aligned-title = Blijf in lijn
|
||||
onboarding-stay_aligned-description = Stel Blijf in lijn in om je trackers in lijn te houden.
|
||||
onboarding-stay_aligned-put_trackers_on-title = Doe je trackers aan
|
||||
onboarding-stay_aligned-put_trackers_on-description = Om je ontspannen houdingen op te slaan, gebruiken we de trackers die je zojuist hebt toegewezen. Doe al je trackers om; je kunt zien welke welke zijn op de afbeelding rechts.
|
||||
onboarding-stay_aligned-put_trackers_on-trackers_warning = Je hebt momenteel minder dan 5 trackers aangesloten en toegewezen! Dit is het minimale aantal trackers dat nodig is om Blijf in lijn goed te laten werken.
|
||||
onboarding-stay_aligned-put_trackers_on-next = Ik heb al mijn trackers aan
|
||||
onboarding-stay_aligned-verify_mounting-title = Controleer je montage
|
||||
onboarding-stay_aligned-verify_mounting-step-0 = Blijf in lijn vereist een goede montage. Anders krijg je geen goede ervaring met Blijf in lijn.
|
||||
onboarding-stay_aligned-verify_mounting-step-1 = 1. Beweeg terwijl je staat.
|
||||
onboarding-stay_aligned-verify_mounting-step-2 = 2. Ga zitten en beweeg je benen en voeten.
|
||||
onboarding-stay_aligned-verify_mounting-step-3 = 3. Als je trackers niet op de juiste plek zitten, druk dan op "Montagekalibratie opnieuw uitvoeren".
|
||||
onboarding-stay_aligned-verify_mounting-redo_mounting = Montagekalibratie opnieuw uitvoeren
|
||||
onboarding-stay_aligned-preparation-title = Voorbereiding
|
||||
onboarding-stay_aligned-preparation-tip = Zorg dat je rechtop staat. Blijf recht vooruit kijken en houd je armen langs je zij.
|
||||
onboarding-stay_aligned-relaxed_poses-standing-title = Ontspannen Staande Houding
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-0 = 1. Ga in een comfortabele houding staan. Ontspan!
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-1-v2 = 2. Druk op de knop "Houding opslaan".
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-title = Ontspannen Zittende Houding op Stoel
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-0 = 1. Ga comfortabel zitten. Ontspan!
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-1-v2 = 2. Druk op de knop "Houding opslaan".
|
||||
onboarding-stay_aligned-relaxed_poses-flat-title = Ontspannen Zittende Houding op de Vloer
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-0 = 1. Ga op de vloer zitten met je benen voor je uit. Ontspan!
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-1-v2 = 2. Druk op de knop "Houding opslaan".
|
||||
onboarding-stay_aligned-relaxed_poses-skip_step = Overslaan
|
||||
onboarding-stay_aligned-done-title = Blijf in lijn ingeschakeld!
|
||||
onboarding-stay_aligned-done-description = Je Blijf in lijn-instelling is voltooid!
|
||||
onboarding-stay_aligned-done-description-2 = De setup is voltooid! Je kunt het proces opnieuw starten als je de houdingen opnieuw wilt kalibreren.
|
||||
onboarding-stay_aligned-previous_step = Vorige
|
||||
onboarding-stay_aligned-next_step = Volgende
|
||||
onboarding-stay_aligned-restart = Herstarten
|
||||
onboarding-stay_aligned-done = Klaar
|
||||
|
||||
## Home
|
||||
|
||||
@@ -1189,6 +1365,11 @@ status_system-StatusSteamVRDisconnected =
|
||||
}
|
||||
status_system-StatusTrackerError = De { $trackerName } tracker heeft een error.
|
||||
status_system-StatusUnassignedHMD = De VR-headset moet worden toegewezen als hoofdtracker.
|
||||
status_system-StatusPublicNetwork =
|
||||
{ $count ->
|
||||
[one] Je netwerkprofiel staat momenteel ingesteld op Openbaar ({ $adapters }). Dit wordt niet aanbevolen voor een goede werking van SlimeVR. <PublicFixLink>Hier lees je hoe je het kunt oplossen.</PublicFixLink>
|
||||
*[other] Sommige van je netwerkadapters staan ingesteld op openbaar: { $adapters }. Dit wordt niet aanbevolen voor een goede werking van SlimeVR. <PublicFixLink>Hier lees je hoe je dit kunt oplossen.</PublicFixLink>
|
||||
}
|
||||
|
||||
## Firmware tool globals
|
||||
|
||||
@@ -1201,7 +1382,7 @@ firmware_tool-loading = Laden...
|
||||
## Firmware tool Steps
|
||||
|
||||
firmware_tool = DIY firmware-tool
|
||||
firmware_tool-description = Hiermee kunt u uw DIY-trackers configureren en flashen
|
||||
firmware_tool-description = Hiermee kan je uw DIY-trackers configureren en flashen
|
||||
firmware_tool-not_available = Oeps, de firmwaretool is momenteel niet beschikbaar. Kom later terug!
|
||||
firmware_tool-not_compatible = De firmwaretool is niet compatibel met deze versie van de server. Gelieve te updaten!
|
||||
firmware_tool-board_step = Selecteer je bord
|
||||
@@ -1287,6 +1468,7 @@ firmware_tool-build_step = Aan het bouwen
|
||||
firmware_tool-build_step-description = De firmware wordt gebouwd, even geduld a.u.b.
|
||||
firmware_tool-flashing_step = Firmware aan het uploaden
|
||||
firmware_tool-flashing_step-description = Je trackers worden geflashed, volg de instructies op het scherm
|
||||
firmware_tool-flashing_step-warning-v2 = Koppel de tracker niet los en zet hem niet uit tijdens het uploadproces, tenzij dit wordt aangegeven. Dit kan je apparaat onbruikbaar maken.
|
||||
firmware_tool-flashing_step-flash_more = Flash meer trackers
|
||||
firmware_tool-flashing_step-exit = Sluit
|
||||
|
||||
@@ -1304,6 +1486,7 @@ firmware_tool-build-ERROR = Kan de firmware niet bouwen
|
||||
## Firmware update status
|
||||
|
||||
firmware_update-status-DOWNLOADING = Firmware wordt gedownload
|
||||
firmware_update-status-NEED_MANUAL_REBOOT-v2 = Zet je tracker uit en daarna weer aan.
|
||||
firmware_update-status-AUTHENTICATING = Authenticatie met de mcu
|
||||
firmware_update-status-UPLOADING = Firmware wordt geüpload
|
||||
firmware_update-status-SYNCING_WITH_MCU = Synchroniseren met de mcu
|
||||
@@ -1356,6 +1539,46 @@ unknown_device-modal-title = Er is een nieuwe tracker gevonden!
|
||||
unknown_device-modal-description = Er is een nieuwe tracker gevonden met MAC-adres <b>{ $deviceId }</b>. Wil je deze verbinden met SlimeVR?
|
||||
unknown_device-modal-confirm = Tuurlijk!
|
||||
unknown_device-modal-forget = Negeer het
|
||||
# VRChat config warnings
|
||||
vrc_config-page-title = VRChat-configuratie waarschuwingen
|
||||
vrc_config-page-desc = Deze pagina toont de status van je VRChat-instellingen en welke instellingen niet compatibel zijn met SlimeVR. Het wordt sterk aanbevolen om eventuele waarschuwingen hier te verhelpen voor de beste gebruikservaring met SlimeVR.
|
||||
vrc_config-page-help = Kan je de instellingen niet finden?
|
||||
vrc_config-page-help-desc = Bekijk onze <a>documentatie over dit onderwerp!</a>
|
||||
vrc_config-page-big_menu = Tracking & IK (Hoofdmenu)
|
||||
vrc_config-page-big_menu-desc = IK-instellingen in het hoofdmenu
|
||||
vrc_config-page-wrist_menu = Tracking & IK (Polsmenu)
|
||||
vrc_config-page-wrist_menu-desc = IK-instellingen in het kleine polsmenu
|
||||
vrc_config-on = Aan
|
||||
vrc_config-off = Uit
|
||||
vrc_config-invalid = Je VRChat-instellingen zijn verkeerd geconfigureerd!
|
||||
vrc_config-show_more = Toon meer
|
||||
vrc_config-setting_name = Naam van de VRChat-instelling
|
||||
vrc_config-recommended_value = Aanbevolen waarde
|
||||
vrc_config-current_value = Huidige waarde
|
||||
vrc_config-mute = Waarschuwing dempen
|
||||
vrc_config-mute-btn = Dempen
|
||||
vrc_config-unmute-btn = Dempen opheffen
|
||||
vrc_config-legacy_mode = Use Legacy IK Solving
|
||||
vrc_config-disable_shoulder_tracking = Disable Shoulder Tracking
|
||||
vrc_config-shoulder_width_compensation = Shoulder Width Compensation
|
||||
vrc_config-spine_mode = FBT Spine Mode
|
||||
vrc_config-tracker_model = FBT Tracker Model
|
||||
vrc_config-avatar_measurement_type = Avatar Measurement
|
||||
vrc_config-calibration_range = Calibration Range
|
||||
vrc_config-calibration_visuals = Display Calibration Visuals
|
||||
vrc_config-user_height = User Real Height
|
||||
vrc_config-spine_mode-UNKNOWN = Onbekend
|
||||
vrc_config-spine_mode-LOCK_BOTH = Lock Both
|
||||
vrc_config-spine_mode-LOCK_HEAD = Lock Head
|
||||
vrc_config-spine_mode-LOCK_HIP = Lock Hip
|
||||
vrc_config-tracker_model-UNKNOWN = Onbekend
|
||||
vrc_config-tracker_model-AXIS = Axis
|
||||
vrc_config-tracker_model-BOX = Box
|
||||
vrc_config-tracker_model-SPHERE = Sphere
|
||||
vrc_config-tracker_model-SYSTEM = Systeem
|
||||
vrc_config-avatar_measurement_type-UNKNOWN = Onbekend
|
||||
vrc_config-avatar_measurement_type-HEIGHT = Height
|
||||
vrc_config-avatar_measurement_type-ARM_SPAN = Arm Span
|
||||
|
||||
## Error collection consent modal
|
||||
|
||||
|
||||
@@ -268,6 +268,7 @@ navbar-settings = Ustawienia
|
||||
|
||||
bvh-start_recording = Nagraj BVH
|
||||
bvh-recording = Nagrywanie...
|
||||
bvh-save_title = Zapisz nagranie BVH
|
||||
|
||||
## Tracking pause
|
||||
|
||||
@@ -308,6 +309,7 @@ widget-imu_visualizer-rotation_raw = Raw
|
||||
widget-imu_visualizer-rotation_preview = Podgląd
|
||||
widget-imu_visualizer-acceleration = Akceleracja
|
||||
widget-imu_visualizer-position = Pozycja
|
||||
widget-imu_visualizer-stay_aligned = Wyrównywanie
|
||||
|
||||
## Widget: Skeleton Visualizer
|
||||
|
||||
@@ -335,6 +337,7 @@ tracker-table-column-temperature = Temp. °C
|
||||
tracker-table-column-linear-acceleration = Akceleracja X/Y/Z
|
||||
tracker-table-column-rotation = Rotacja X/Y/Z
|
||||
tracker-table-column-position = Pozycja X/Y/Z
|
||||
tracker-table-column-stay_aligned = Wyrównywanie
|
||||
tracker-table-column-url = URL
|
||||
|
||||
## Tracker rotation
|
||||
@@ -403,6 +406,7 @@ tracker-settings-forget-label = Zapomnij o trackerze
|
||||
tracker-settings-update-unavailable = Nie można zaktualizować (zrób to sam)
|
||||
tracker-settings-update-low-battery = Nie można zaktualizować. Bateria poniżej 50%
|
||||
tracker-settings-update-up_to_date = Aktualny
|
||||
tracker-settings-update-blocked = Aktualizacja niedostępna. Brak innych wersji
|
||||
tracker-settings-update-available = Wersja { $versionName } jest już dostępna
|
||||
tracker-settings-update = Zaktualizuj teraz
|
||||
tracker-settings-update-title = Wersja oprogramowania
|
||||
@@ -472,6 +476,7 @@ mounting_selection_menu-close = Zamknij
|
||||
settings-sidebar-title = Ustawienia
|
||||
settings-sidebar-general = Ogólne
|
||||
settings-sidebar-tracker_mechanics = Mechanika trackerów
|
||||
settings-sidebar-stay_aligned = Wyrównywanie
|
||||
settings-sidebar-fk_settings = Ustawienia śledzenia
|
||||
settings-sidebar-gesture_control = Sterowanie gestami
|
||||
settings-sidebar-interface = Interfejs
|
||||
@@ -481,7 +486,9 @@ settings-sidebar-utils = Narzędzia
|
||||
settings-sidebar-serial = Konsola szeregowa
|
||||
settings-sidebar-appearance = Wygląd
|
||||
settings-sidebar-notifications = Powiadomienia
|
||||
settings-sidebar-behavior = Zachowanie
|
||||
settings-sidebar-firmware-tool = Narzędzie do oprogramowania sprzętowego DIY
|
||||
settings-sidebar-vrc_warnings = Ostrzeżenia dotyczące konfiguracji VRChat
|
||||
settings-sidebar-advanced = Zaawansowany
|
||||
|
||||
## SteamVR settings
|
||||
@@ -563,6 +570,25 @@ settings-general-tracker_mechanics-use_mag_on_all_trackers-description =
|
||||
Wykorzystuje magnetometr we wszystkich trackerach, które mają kompatybilne oprogramowanie sprzętowe, redukując dryf w stabilnych środowiskach magnetycznych.¶
|
||||
Można wyłączyć dla każdego modułu śledzącego w ustawieniach modułu śledzącego. <b>Proszę nie wyłączać żadnego modułu śledzącego podczas przełączania!</b>
|
||||
settings-general-tracker_mechanics-use_mag_on_all_trackers-label = Użyj magnetometru na trackerach
|
||||
settings-stay_aligned = Wyrównywanie
|
||||
settings-stay_aligned-description = Wyrównywanie zmniejsza efekt driftu, stopniowo dostosowując trackery do twoich zrelaksowanych póz.
|
||||
settings-stay_aligned-setup-label = Konfiguracja Opcji Wyrównywania
|
||||
settings-stay_aligned-setup-description = Musisz ukończyć konfigurację, aby włączyć opcję Wyrównywania.
|
||||
settings-stay_aligned-warnings-drift_compensation = ⚠ Wyłącz kompensację Driftu, będzie ona kolidować z opcją Wyrównywania!
|
||||
settings-stay_aligned-enabled-label = Dostosuj trackery
|
||||
settings-stay_aligned-hide_yaw_correction-label = Ukryj dopasowanie (do porównania bez opcji Wyrównywania)
|
||||
settings-stay_aligned-general-label = Ogólne
|
||||
settings-stay_aligned-relaxed_poses-label = Zrelaksowane pozy
|
||||
settings-stay_aligned-relaxed_poses-description = Opcja Wyrównywania wykorzystuje Twoje zrelaksowane pozy, aby utrzymać trackery w jednej linii. Użyj opcji "Konfiguracja Opcji Wyrównywania", aby zaktualizować te pozy.
|
||||
settings-stay_aligned-relaxed_poses-standing = Dostosuj trackery w pozycji stojącej
|
||||
settings-stay_aligned-relaxed_poses-sitting = Dostosuj trackery, siedząc na krześle
|
||||
settings-stay_aligned-relaxed_poses-flat = Dostosuj trackery, siedząc na podłodze lub leżąc na plecach
|
||||
settings-stay_aligned-relaxed_poses-save_pose = Zapisz pozę
|
||||
settings-stay_aligned-relaxed_poses-reset_pose = Zresetuj Pozycję
|
||||
settings-stay_aligned-relaxed_poses-close = Zamknij
|
||||
settings-stay_aligned-debug-label = Debugowanie
|
||||
settings-stay_aligned-debug-description = Proszę dołączać ustawienia, podczas zgłaszania problemów z opcją Wyrównywania.
|
||||
settings-stay_aligned-debug-copy-label = Skopiuj ustawienia do schowka
|
||||
|
||||
## FK/Tracking settings
|
||||
|
||||
@@ -725,6 +751,9 @@ settings-interface-behavior-error_tracking-description_v2 =
|
||||
|
||||
Aby zapewnić jak najlepsze wrażenia użytkownika, gromadzimy anonimowe raporty o błędach, wskaźniki wydajności i informacje o systemie operacyjnym. Pomaga nam to wykrywać błędy i problemy ze SlimeVR. Dane te są zbierane za pomocą Sentry.io.
|
||||
settings-interface-behavior-error_tracking-label = Wysyłanie błędów do deweloperów
|
||||
settings-interface-behavior-bvh_directory = Ścieżka do zapisywania nagrań BVH
|
||||
settings-interface-behavior-bvh_directory-description = Wybierz ścieżkę domyślną, w której chcesz zapisywać nagrania BVH.
|
||||
settings-interface-behavior-bvh_directory-label = Ścieżka do nagrań BVH
|
||||
|
||||
## Serial settings
|
||||
|
||||
@@ -788,6 +817,7 @@ settings-osc-vrchat-description-v1 =
|
||||
settings-osc-vrchat-enable = Zezwól
|
||||
settings-osc-vrchat-enable-description = Zezwól na wysyłanie i odbieranie danych.
|
||||
settings-osc-vrchat-enable-label = Zezwól
|
||||
settings-osc-vrchat-oscqueryEnabled = Włącz OSCQuery
|
||||
settings-osc-vrchat-oscqueryEnabled-description =
|
||||
OSCQuery automatycznie wykrywa uruchomione instancje VRChat i wysyła im dane.
|
||||
Może również reklamować się do nich w celu otrzymania danych HMD i administratora.
|
||||
@@ -994,7 +1024,7 @@ onboarding-connect_tracker-next = Połączyłem już wszystkie trackery
|
||||
|
||||
onboarding-calibration_tutorial = Samouczek kalibracji IMU
|
||||
onboarding-calibration_tutorial-subtitle = Pomoże to ograniczyć dryf trackera!
|
||||
onboarding-calibration_tutorial-description = Za każdym razem, gdy włączasz trackery, muszą one chwilę polerzeć na płaskiej powierzchni, aby się skalibrować. Zróbmy to samo, klikając przycisk „Kalibruj”, <b>nie ruszaj ich!</b>
|
||||
onboarding-calibration_tutorial-description-v1 = Po włączeniu trackerów umieść je na chwilę na stabilnej powierzchni, aby umożliwić kalibrację. Kalibrację można przeprowadzić w dowolnym momencie po włączeniu trackerów - ta strona zawiera po prostu samouczek. Aby rozpocząć, kliknij przycisk "{ onboarding-calibration_tutorial-calibrate }", a następnie <b>nie ruszaj swoich trackerów!</b>
|
||||
onboarding-calibration_tutorial-calibrate = Położyłem trackery na stole
|
||||
onboarding-calibration_tutorial-status-waiting = Czekam na Ciebie
|
||||
onboarding-calibration_tutorial-status-calibrating = Kalibracja
|
||||
@@ -1165,6 +1195,9 @@ onboarding-automatic_mounting-mounting_reset-title = Kalibracja Pozycji
|
||||
onboarding-automatic_mounting-mounting_reset-step-0 = 1. Zrób pozycje "na Małysza" z wygiętymi nogami, tułowiem pochylonym do przodu z wygiętymi rękami.
|
||||
onboarding-automatic_mounting-mounting_reset-step-1 = 2. Naciśnij "Zresetuj Położenie" i poczekaj 3 sekundy zanim trackery się zresetują.
|
||||
onboarding-automatic_mounting-preparation-title = Przygotowania
|
||||
onboarding-automatic_mounting-preparation-v2-step-0 = 1. Naciśnij przycisk "Pełny reset".
|
||||
onboarding-automatic_mounting-preparation-v2-step-1 = 2. Stań prosto z rękami po bokach. Upewnij się, że patrzysz przed siebie.
|
||||
onboarding-automatic_mounting-preparation-v2-step-2 = 3. Utrzymaj pozycję, aż skończy się 3-sekundowy timer.
|
||||
onboarding-automatic_mounting-put_trackers_on-title = Załóż trackery
|
||||
onboarding-automatic_mounting-put_trackers_on-description = Aby skalibrować rotacje, użyjemy trackerów które przypisano przed chwilą. Załóż wszystkie trackery, możesz je odróznić na postaci po prawej.
|
||||
onboarding-automatic_mounting-put_trackers_on-next = Wszystkie trackery założone
|
||||
@@ -1298,6 +1331,37 @@ onboarding-scaled_proportions-done-description = Proporcje Twojego ciała powinn
|
||||
|
||||
## Stay Aligned setup
|
||||
|
||||
onboarding-stay_aligned-title = Wyrównywanie
|
||||
onboarding-stay_aligned-description = Skonfiguruj opcję Wyrównywania, aby Twoje trackery były wyrównane.
|
||||
onboarding-stay_aligned-put_trackers_on-title = Załóż trackery
|
||||
onboarding-stay_aligned-put_trackers_on-description = Aby skalibrować proporcje, użyjemy trackerów które przed chwilą przypisałeś. Załóż wszystkie trackery, będziesz widział który to który na postaci po prawej.
|
||||
onboarding-stay_aligned-put_trackers_on-trackers_warning = Masz mniej niż 5 trackerów aktualnie podłączonych i przypisanych! Jest to minimalna liczba elementów śledzących wymaganych do prawidłowego działania opcji Wyrównywania.
|
||||
onboarding-stay_aligned-put_trackers_on-next = Mam wszystkie trackery założone
|
||||
onboarding-stay_aligned-verify_mounting-title = Sprawdź swój montaż
|
||||
onboarding-stay_aligned-verify_mounting-step-0 = Opcja Wyrównywania wymaga stabilnego mocowania trackera. W innym przypadku będziesz miał złe rezultaty.
|
||||
onboarding-stay_aligned-verify_mounting-step-1 = 1. Poruszaj się podczas stania.
|
||||
onboarding-stay_aligned-verify_mounting-step-2 = 2. Usiądź i poruszaj nogami i stopami.
|
||||
onboarding-stay_aligned-verify_mounting-step-3 = 3. Jeśli Twoje trackery nie znajdują się we właściwym miejscu, naciśnij "Ponów kalibrację montażu".
|
||||
onboarding-stay_aligned-verify_mounting-redo_mounting = Ponów kalibrację montażu
|
||||
onboarding-stay_aligned-preparation-title = Przygotowania
|
||||
onboarding-stay_aligned-preparation-tip = Upewnij się, że stoisz prosto. Patrz przed siebie z rękami opuszczonymi po bokach.
|
||||
onboarding-stay_aligned-relaxed_poses-standing-title = Zrelaksowana pozycja stojąca
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-0 = 1. Stań w wygodnej pozycji. Zrelaksuj się!
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-1-v2 = 2. Naciśnij przycisk "Zapisz pozę".
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-title = Zrelaksowana pozycja siedząca na krześle
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-0 = 1. Usiądź w wygodnej pozycji. Zrelaksuj się!
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-1-v2 = 2. Naciśnij przycisk "Zapisz pozę".
|
||||
onboarding-stay_aligned-relaxed_poses-flat-title = Zrelaksowana pozycja siedząca na podłodze
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-0 = 1. Usiądź na podłodze z nogami wysuniętymi do przodu. Zrelaksuj się!
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-1-v2 = 2. Naciśnij przycisk "Zapisz pozę".
|
||||
onboarding-stay_aligned-relaxed_poses-skip_step = Pomiń
|
||||
onboarding-stay_aligned-done-title = Wyrównywanie Włączone!
|
||||
onboarding-stay_aligned-done-description = Konfiguracja Wyrównywania jest zakończona!
|
||||
onboarding-stay_aligned-done-description-2 = Konfiguracja została zakończona! Możesz ponownie uruchomić proces, jeśli chcesz ponownie skalibrować pozy.
|
||||
onboarding-stay_aligned-previous_step = Poprzednie
|
||||
onboarding-stay_aligned-next_step = Następne
|
||||
onboarding-stay_aligned-restart = Restart
|
||||
onboarding-stay_aligned-done = Gotowy
|
||||
|
||||
## Home
|
||||
|
||||
@@ -1322,6 +1386,12 @@ status_system-StatusSteamVRDisconnected =
|
||||
}
|
||||
status_system-StatusTrackerError = Tracker { $trackerName } ma błąd.
|
||||
status_system-StatusUnassignedHMD = Headset powinien być przypisany do śledzenia głowy.
|
||||
status_system-StatusPublicNetwork =
|
||||
{ $count ->
|
||||
[one] Twoja karta sieciowa jest ustawiona jako publiczna: { $adapters }. Nie jest to zalecane, aby SlimeVR działał poprawnie. <PublicFixLink>Zobacz, jak to naprawić tutaj.</PublicFixLink>
|
||||
[few] Niektóre karty sieciowe są ustawione jako publiczne: { $adapters }. Nie jest to zalecane, aby SlimeVR działał poprawnie. <PublicFixLink>Zobacz, jak to naprawić tutaj.</PublicFixLink>
|
||||
*[many] Dużo twoich karty sieciowych jest ustawionych jako publiczne: { $adapters }. Nie jest to zalecane, aby SlimeVR działał poprawnie. <PublicFixLink>Zobacz, jak to naprawić tutaj.</PublicFixLink>
|
||||
}
|
||||
|
||||
## Firmware tool globals
|
||||
|
||||
@@ -1423,6 +1493,7 @@ firmware_tool-build_step = Building
|
||||
firmware_tool-build_step-description = Trwa tworzenie oprogramowania sprzętowego. Proszę czekać
|
||||
firmware_tool-flashing_step = Flashing
|
||||
firmware_tool-flashing_step-description = Twoje trackery migają. Postępuj zgodnie z instrukcjami wyświetlanymi na ekranie
|
||||
firmware_tool-flashing_step-warning-v2 = Nie odłączaj ani nie wyłączaj trackera podczas procesu przesyłania, chyba że zostaniesz o to poproszony, może to spowodować, że twoje urządzenie stanie się bezużyteczne.
|
||||
firmware_tool-flashing_step-flash_more = Flashuj więcej trackerów
|
||||
firmware_tool-flashing_step-exit = Wyjście
|
||||
|
||||
@@ -1440,6 +1511,7 @@ firmware_tool-build-ERROR = Nie można zbudować oprogramowania sprzętowego
|
||||
## Firmware update status
|
||||
|
||||
firmware_update-status-DOWNLOADING = Pobieranie oprogramowania sprzętowego
|
||||
firmware_update-status-NEED_MANUAL_REBOOT-v2 = Wyłącz i ponownie włącz swój tracker
|
||||
firmware_update-status-AUTHENTICATING = Uwierzytelnianie za pomocą MCU
|
||||
firmware_update-status-UPLOADING = Przesyłanie oprogramowania sprzętowego
|
||||
firmware_update-status-SYNCING_WITH_MCU = Synchronizacja z MCU
|
||||
@@ -1510,6 +1582,9 @@ vrc_config-show_more = Pokaż więcej
|
||||
vrc_config-setting_name = Nazwa ustawienia VRChat
|
||||
vrc_config-recommended_value = Zalecana wartość
|
||||
vrc_config-current_value = Bieżąca wartość
|
||||
vrc_config-mute = Wycisz Ostrzeżenie
|
||||
vrc_config-mute-btn = Wycisz
|
||||
vrc_config-unmute-btn = Odcisz
|
||||
vrc_config-legacy_mode = Korzystanie ze starszego rozwiązywania kinematyki odwrotnej
|
||||
vrc_config-disable_shoulder_tracking = Wyłącz śledzenie ramienia
|
||||
vrc_config-shoulder_width_compensation = Kompensacja szerokości barku
|
||||
|
||||
@@ -53,7 +53,7 @@ body_part-LEFT_LOWER_ARM = แขนซ้ายส่วนล่าง
|
||||
body_part-LEFT_HAND = มือซ้าย
|
||||
body_part-LEFT_UPPER_LEG = ต้นขาซ้าย
|
||||
body_part-LEFT_LOWER_LEG = ข้อเท้าซ้าย
|
||||
body_part-LEFT_FOOT = เท้าขวา
|
||||
body_part-LEFT_FOOT = เท้าซ้าย
|
||||
body_part-LEFT_THUMB_METACARPAL = ฝ่ามือนิ้วโป้งซ้าย
|
||||
body_part-LEFT_THUMB_PROXIMAL = โคนนิ้วโป้งซ้าย
|
||||
body_part-LEFT_THUMB_DISTAL = ปลายนิ้วโป้งซ้าย
|
||||
@@ -992,9 +992,6 @@ onboarding-connect_tracker-next = ฉันเชื่อมต่อแทร
|
||||
|
||||
onboarding-calibration_tutorial = บทเรียนการปรับเทียบ IMU
|
||||
onboarding-calibration_tutorial-subtitle = นี่จะเป็นการช่วยลดค่าดริฟท์ของแทร็กเกอร์
|
||||
onboarding-calibration_tutorial-description =
|
||||
ทุกครั้งที่มีการใช้แทร็กเกอร์ คุณควรจะวางไว้บนพื้นเรียบสักครู่เพื่อเริ่มต้นการปรับเทียบ งั้นเรามาทำแบบนั้นกันเลยด้วยการคลิกไปที่
|
||||
"{ onboarding-calibration_tutorial-calibrate }" <b>และอย่าขยับมัน!</b>
|
||||
onboarding-calibration_tutorial-calibrate = ฉันได้วางแทร็กเกอร์ไว้บนโต๊ะแล้ว
|
||||
onboarding-calibration_tutorial-status-waiting = เรารอคุณอยู่
|
||||
onboarding-calibration_tutorial-status-calibrating = กำลังปรับเทียบ
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
websocket-connecting = Đang kết nối với máy chủ
|
||||
websocket-connection_lost = Kết nối với máy chủ đã mất. Đang kết nối lại...
|
||||
websocket-connection_lost-desc = Máy chủ SlimeVR bị dừng. Hãy kiểm tra nhật ký logs và khởi động lại chương trình.
|
||||
websocket-timedout = Không thể tìm thấy máy chủ
|
||||
websocket-timedout-desc = Có vẻ như máy chủ SlimeVR đã bị sập hoặc hết thời gian chờ. Vui lòng kiểm tra nhật ký logs và khởi động lại chương trình.
|
||||
websocket-error-close = Thoát SlimeVR
|
||||
websocket-error-logs = Mở thư mục nhật ký logs
|
||||
|
||||
## Update notification
|
||||
|
||||
@@ -50,6 +55,11 @@ body_part-LEFT_UPPER_LEG = Bắp chân trái
|
||||
body_part-LEFT_LOWER_LEG = Cẳng chân trái
|
||||
body_part-LEFT_FOOT = Bàn chân trái
|
||||
|
||||
## BoardType
|
||||
|
||||
board_type-MOCOPI = Sony Mocopi
|
||||
board_type-WEMOSWROOM02 = Wemos Wroom-02 D1 Mini
|
||||
|
||||
## Proportions
|
||||
|
||||
skeleton_bone-NONE = Chưa được gán
|
||||
@@ -421,9 +431,6 @@ settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Tính
|
||||
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = Tính trung bình của chiều quay đầu gối ngáp và lăn bằng mắt cá chân '
|
||||
settings-general-fk_settings-self_localization-title = Chế độ Mocap
|
||||
settings-general-fk_settings-self_localization-description = Chế độ Mocap cho phép bộ xương theo dõi đại khái vị trí của chính nó mà không cần kính VR hoặc các thiết bị theo dõi khác. Lưu ý rằng điều này yêu cầu bộ theo dõi chân và đầu để hoạt động và chức năng này vẫn đang trong quá trình thử nghiệm.
|
||||
settings-general-fk_settings-vive_emulation-title = Giả lập tracker Vive
|
||||
settings-general-fk_settings-vive_emulation-description = Giả lập cách tracker của Vive gặp vấn đề với việc theo dõi eo, đây là 1 tính năng được làm cho vui và sẽ làm giảm độ chính xác
|
||||
settings-general-fk_settings-vive_emulation-label = Giả lập tracker Vive
|
||||
|
||||
## Gesture control settings (tracker tapping)
|
||||
|
||||
@@ -485,6 +492,12 @@ settings-general-interface-feedback_sound-volume = Âm lượng phản hồi
|
||||
settings-general-interface-connected_trackers_warning = Cảnh báo với thiết bị đã kết nối
|
||||
settings-general-interface-connected_trackers_warning-description = Tùy chọn này sẽ hiển thị cửa sổ bật lên mỗi khi bạn thử thoát khỏi SlimeVR trong khi có một hoặc nhiều thiết bị theo dõi được kết nối. Nó nhắc nhở bạn tắt trình theo dõi khi bạn hoàn tất để duy trì tuổi thọ pin.
|
||||
settings-general-interface-connected_trackers_warning-label = Cảnh báo thiết bị đã kết nối khi thoát chương trình
|
||||
|
||||
## Behavior settings
|
||||
|
||||
settings-general-interface-dev_mode = Chế độ nhà phát triển
|
||||
settings-general-interface-dev_mode-description = Hữu dụng nếu cần thêm thông tin chi tiết của tracker hay can thiệp sâu hơn vào tracker
|
||||
settings-general-interface-dev_mode-label = Chế độ nhà phát triển
|
||||
settings-general-interface-use_tray = Thu nhỏ vào khay hệ thống
|
||||
settings-general-interface-use_tray-description = Cho phép bạn đóng cửa sổ mà không cần đóng máy chủ SlimeVR để bạn có thể tiếp tục sử dụng nó mà không bị GUI làm phiền.
|
||||
settings-general-interface-use_tray-label = Thu nhỏ vào khay hệ thống
|
||||
@@ -601,12 +614,6 @@ settings-osc-vmc-network-address-description = Chọn địa chỉ để gửi d
|
||||
settings-osc-vmc-network-address-placeholder = Địa chỉ IPV4
|
||||
settings-osc-vmc-vrm = Model VRM
|
||||
settings-osc-vmc-vrm-description = Tải mô hình VRM để cho phép neo đầu và cho phép khả năng tương thích cao hơn với các ứng dụng khác.
|
||||
settings-osc-vmc-vrm-model_unloaded = Chưa có mô hình tải lên
|
||||
settings-osc-vmc-vrm-model_loaded =
|
||||
{ $titled ->
|
||||
[true] Mô hình đã được tải: { $name }
|
||||
*[other] Mô hình chưa có tiêu đề đã được tải
|
||||
}
|
||||
settings-osc-vmc-vrm-file_select = Kéo và thả mô hình để sử dụng hoặc <u>duyệt file</u>
|
||||
settings-osc-vmc-anchor_hip = Cố định ở hông
|
||||
settings-osc-vmc-anchor_hip-description = Cố định theo dõi ở hông, hữu ích cho VTubing ngồi. Nếu tắt, hãy tải mô hình VRM.
|
||||
@@ -622,8 +629,6 @@ settings-utils-advanced-reset-gui = Đặt lại cài đặt GUI
|
||||
settings-utils-advanced-reset-all-label = Đặt lại tất cả
|
||||
settings-utils-advanced-reset_warning-reset = Đặt lại cài đặt
|
||||
settings-utils-advanced-reset_warning-cancel = Hủy
|
||||
settings-utils-advanced-open_data = Thư mục dữ liệu
|
||||
settings-utils-advanced-open_data-description = Mở thư mục dữ liệu của SlimeVR trong tệp, chứa các tệp cấu hình và logs.
|
||||
settings-utils-advanced-open_data-label = Mở thư mục
|
||||
|
||||
## Setup/onboarding menu
|
||||
@@ -731,7 +736,6 @@ onboarding-connect_tracker-next = Đã kết nối với tất cả tracker
|
||||
|
||||
onboarding-calibration_tutorial = Hướng dẫn hiệu chuẩn IMU
|
||||
onboarding-calibration_tutorial-subtitle = Cái này sẽ giúp giảm trôi trượt theo dõi!
|
||||
onboarding-calibration_tutorial-description = Mỗi khi bạn bật thiết bị theo dõi, chúng cần nghỉ ngơi một lúc trên bề mặt phẳng để hiệu chỉnh. Hãy làm điều tương tự bằng cách nhấp vào nút "{ onboarding-calibration_tutorial-calibrate }", <b>và không di chuyển chúng!</b>
|
||||
onboarding-calibration_tutorial-calibrate = Tôi đã đặt thiết bị theo dõi của mình lên bàn
|
||||
onboarding-calibration_tutorial-status-waiting = Đang chờ bạn hoàn thành
|
||||
onboarding-calibration_tutorial-status-calibrating = Đang hiệu chuẩn
|
||||
@@ -895,44 +899,14 @@ onboarding-automatic_mounting-mounting_reset-title = Đặt lại hướng gắn
|
||||
onboarding-automatic_mounting-mounting_reset-step-0 = 1. Đứng khom người như tư thế trượt tuyết với đầu gối khom lại, thân trên hướng tới trước và hai tay co lại để giữ thăng bằng như hình bên
|
||||
onboarding-automatic_mounting-mounting_reset-step-1 = 2. Nhấn nút đặt lại và chờ 3 giây trước khi hệ thống cân chỉnh hướng gắn tracker
|
||||
onboarding-automatic_mounting-preparation-title = Chuẩn bị tư thế
|
||||
onboarding-automatic_mounting-preparation-step-0 = 1. Đứng thẳng với hai tay duỗi thẳng
|
||||
onboarding-automatic_mounting-preparation-step-1 = 2. Nhấn nút đặt lại và chờ 3 giây trước khi tracker được đặt lại.
|
||||
onboarding-automatic_mounting-put_trackers_on-title = Đeo tracker lên người
|
||||
onboarding-automatic_mounting-put_trackers_on-description = Để cân chỉnh hướng gắn của tracker, SlimeVR sẽ tiến hành đo góc nghiêng của tracker khi đang đeo để cân chỉnh hướng gắn, hãy đeo tracker theo đúng vị trí đã thiết lập
|
||||
onboarding-automatic_mounting-put_trackers_on-next = Tiếp tục
|
||||
|
||||
## Tracker proportions method choose
|
||||
|
||||
onboarding-choose_proportions = Phương pháp hiệu chuẩn tỷ lệ nào để sử dụng?
|
||||
# Multiline string
|
||||
onboarding-choose_proportions-description-v1 =
|
||||
Tỷ lệ cơ thể được sử dụng để biết các số đo của cơ thể bạn. Họ được yêu cầu tính toán vị trí của trình theo dõi.
|
||||
Khi tỷ lệ cơ thể của bạn không khớp với tỷ lệ được lưu, độ chính xác theo dõi của bạn sẽ kém hơn và bạn sẽ nhận thấy những thứ như trượt băng hoặc trượt, hoặc cơ thể của bạn không khớp với hình đại diện của bạn.
|
||||
<b>Bạn chỉ cần đo cơ thể của bạn một lần!</b> Trừ khi chúng sai hoặc cơ thể bạn đã thay đổi, thì bạn không cần phải làm lại.
|
||||
onboarding-choose_proportions-auto_proportions = Đo kích thước cơ thể tự động
|
||||
# Italicized text
|
||||
onboarding-choose_proportions-auto_proportions-subtitle = Khuyến khích dùng
|
||||
onboarding-choose_proportions-auto_proportions-descriptionv3 =
|
||||
Tính năng này sẽ đoán tỷ lệ cơ thể của bạn bằng cách ghi lại một mẫu chuyển động của bạn và chuyển nó qua một thuật toán.
|
||||
|
||||
<b>Tính năng này sẽ yêu cầu headset của bạn (HMD) được kết nối với SlimeVR và đang nằm ở trên đầu của bạn!</b>
|
||||
onboarding-choose_proportions-manual_proportions = Đo kích thước cơ thể thủ công
|
||||
# Italicized text
|
||||
onboarding-choose_proportions-manual_proportions-subtitle = Cho chính xác
|
||||
onboarding-choose_proportions-manual_proportions-description = Tính năng này sẽ cho phép bạn điều chỉnh tỉ lệ cơ thể của mình theo cách thủ công bằng cách chỉnh sửa các con số một cách trực tiếp
|
||||
onboarding-choose_proportions-export = Xuất tỉ lệ cơ thể
|
||||
onboarding-choose_proportions-import = Nhập tỉ lệ cơ thể
|
||||
onboarding-choose_proportions-import-success = Đã được nhập
|
||||
onboarding-choose_proportions-import-failed = Thất bại
|
||||
onboarding-choose_proportions-file_type = File tỉ lệ cơ thể
|
||||
|
||||
## Tracker manual proportions setup
|
||||
## Tracker manual proportions setupa
|
||||
|
||||
onboarding-manual_proportions-back = Quay lại cân chỉnh hướng gắn
|
||||
onboarding-manual_proportions-title = Đo kích thước cơ thể thủ công
|
||||
onboarding-manual_proportions-precision = Cân chỉnh cụ thể (giảm hệ số chỉnh)
|
||||
onboarding-manual_proportions-auto = Đo kích thước cơ thể tự động
|
||||
onboarding-manual_proportions-ratio = Điều chỉnh theo nhóm tỷ lệ
|
||||
|
||||
## Tracker automatic proportions setup
|
||||
|
||||
@@ -953,20 +927,11 @@ onboarding-automatic_proportions-requirements-descriptionv2 =
|
||||
Headset của bạn đang báo cáo dữ liệu vị trí cho máy chủ SlimeVR (điều này thường có nghĩa là SteamVR đang chạy và kết nối với SlimeVR bằng driver SteamVR của SlimeVR).
|
||||
Tracking của bạn đang hoạt động và thể hiện chính xác các chuyển động của bạn (ví dụ: bạn đã thực hiện thiết đặt lại hoàn toàn và chúng di chuyển đúng hướng khi đá, cúi xuống, ngồi, v.v.).
|
||||
onboarding-automatic_proportions-requirements-next = Tôi đã đọc các yêu cầu
|
||||
onboarding-automatic_proportions-check_height-title = Kiểm tra chiều cao của bạn
|
||||
onboarding-automatic_proportions-check_height-description = Chúng tôi sử dụng chiều cao của bạn làm cơ sở cho các phép đo của chúng tôi bằng cách sử dụng chiều cao của headset (HMD) làm chiều cao ước tính thực tế của bạn, nhưng tốt hơn hết bạn nên tự kiểm tra xem chúng có đúng không!
|
||||
# All the text is in bold!
|
||||
onboarding-automatic_proportions-check_height-calculation_warning = Vui lòng nhấn nút trong khi đứng <u>thẳng</u> để tính chiều cao của bạn. Bạn có 3 giây sau khi nhấn nút!
|
||||
onboarding-automatic_proportions-check_height-guardian_tip =
|
||||
Nếu bạn đang sử dụng Kính VR Standalone, hãy đảm bảo có guardian /
|
||||
Ranh giới được bật để chiều cao của bạn là chính xác!
|
||||
onboarding-automatic_proportions-check_height-fetch_height = Tôi đang đứng!
|
||||
# Context is that the height is unknown
|
||||
onboarding-automatic_proportions-check_height-unknown = Không rõ
|
||||
# Shows an element below it
|
||||
onboarding-automatic_proportions-check_height-hmd_height1 = Chiều cao của HMD là
|
||||
# Shows an element below it
|
||||
onboarding-automatic_proportions-check_height-height1 = vậy chiều cao thật của bạn là
|
||||
onboarding-automatic_proportions-check_height-next_step = Những chỉ số này là đúng
|
||||
onboarding-automatic_proportions-start_recording-title = Chuẩn bị đo
|
||||
onboarding-automatic_proportions-start_recording-description = Phần mềm sẽ đo một số chuyển động, cử chỉ cụ thể, hãy chuẩn bị cho việc di chuyển theo yêu cầu trong phần tiếp theo
|
||||
@@ -997,11 +962,17 @@ onboarding-automatic_proportions-verify_results-redo = Thử lại
|
||||
onboarding-automatic_proportions-verify_results-confirm = Kết quả tương đối chính xác
|
||||
onboarding-automatic_proportions-done-title = Đã lưu chỉ số đo
|
||||
onboarding-automatic_proportions-done-description = Quá trình đo đã hoàn tất
|
||||
onboarding-automatic_proportions-error_modal =
|
||||
<b>Lưu ý:</b> Một lỗi đã được tìm thấy trong khi ước tính tỷ lệ cơ thể!
|
||||
Vui lòng <docs>kiểm tra hướng dẫn</docs> hoặc tham gia <discord>Discord</discord> của chúng tôi để được trợ giúp ^_^
|
||||
onboarding-automatic_proportions-error_modal-confirm = Đã hiểu!
|
||||
|
||||
## Tracker scaled proportions setup
|
||||
|
||||
|
||||
## Tracker scaled proportions reset
|
||||
|
||||
|
||||
## Stay Aligned setup
|
||||
|
||||
|
||||
## Home
|
||||
|
||||
home-no_trackers = Chưa có thiết bị nào được phát hiện hoặc điều ra
|
||||
@@ -1026,6 +997,21 @@ status_system-StatusSteamVRDisconnected =
|
||||
status_system-StatusTrackerError = Tracker { $trackerName } có lỗi.
|
||||
status_system-StatusUnassignedHMD = Kính thực tế ảo VR này nên được giao là bộ theo dõi đầu.
|
||||
|
||||
## Firmware tool globals
|
||||
|
||||
|
||||
## Firmware tool Steps
|
||||
|
||||
|
||||
## firmware tool build status
|
||||
|
||||
|
||||
## Firmware update status
|
||||
|
||||
|
||||
## Dedicated Firmware Update Page
|
||||
|
||||
|
||||
## Tray Menu
|
||||
|
||||
tray_menu-show = Xem
|
||||
@@ -1053,3 +1039,6 @@ unknown_device-modal-description =
|
||||
Bạn có muốn kết nối nó với SlimeVR không?
|
||||
unknown_device-modal-confirm = Chắc!
|
||||
unknown_device-modal-forget = Bỏ qua
|
||||
|
||||
## Error collection consent modal
|
||||
|
||||
|
||||
@@ -233,6 +233,8 @@ reset-reset_all_warning_default-v2 =
|
||||
您确定要执行此操作吗?
|
||||
reset-full = 完整重置
|
||||
reset-mounting = 重置佩戴
|
||||
reset-mounting-feet = 重置脚部佩戴
|
||||
reset-mounting-fingers = 重置手指佩戴
|
||||
reset-yaw = 重置航向轴
|
||||
|
||||
## Serial detection stuff
|
||||
@@ -258,6 +260,7 @@ navbar-settings = 设置
|
||||
|
||||
bvh-start_recording = 录制 BVH 文件
|
||||
bvh-recording = 录制中...
|
||||
bvh-save_title = 保存BVH记录
|
||||
|
||||
## Tracking pause
|
||||
|
||||
@@ -395,6 +398,7 @@ tracker-settings-forget-label = 忘记追踪器
|
||||
tracker-settings-update-unavailable = 无法升级(DIY)
|
||||
tracker-settings-update-low-battery = 无法更新。当前电池电量低于 50%
|
||||
tracker-settings-update-up_to_date = 已是最新
|
||||
tracker-settings-update-blocked = 更新不可用。没有其他可用版本
|
||||
tracker-settings-update-available = { $versionName } 现在可用
|
||||
tracker-settings-update = 立即更新
|
||||
tracker-settings-update-title = 固件版本
|
||||
@@ -573,6 +577,7 @@ settings-stay_aligned-relaxed_poses-sitting = 椅子上放松姿势
|
||||
settings-stay_aligned-relaxed_poses-flat = 地面/平躺放松姿势
|
||||
settings-stay_aligned-relaxed_poses-save_pose = 保存姿势
|
||||
settings-stay_aligned-relaxed_poses-reset_pose = 重置姿势
|
||||
settings-stay_aligned-relaxed_poses-close = 关闭
|
||||
settings-stay_aligned-debug-label = 调试
|
||||
settings-stay_aligned-debug-description = 在报告持续校准相关问题时,请包含您的以下设置信息
|
||||
settings-stay_aligned-debug-copy-label = 复制设置信息到剪贴板
|
||||
@@ -727,6 +732,9 @@ settings-interface-behavior-error_tracking-description_v2 =
|
||||
|
||||
为了提供最佳用户体验,我们会收集匿名错误报告、性能指标和操作系统信息。这有助于我们检测 SlimeVR 的错误和问题。这些指标将通过 Sentry.io 收集。
|
||||
settings-interface-behavior-error_tracking-label = 向开发人员发送错误信息
|
||||
settings-interface-behavior-bvh_directory = BVH记录保存目录
|
||||
settings-interface-behavior-bvh_directory-description = 选择保存BVH记录文件的目录
|
||||
settings-interface-behavior-bvh_directory-label = BVH记录保存目录
|
||||
|
||||
## Serial settings
|
||||
|
||||
@@ -997,7 +1005,7 @@ onboarding-connect_tracker-next = 所有的追踪器都连接好了
|
||||
|
||||
onboarding-calibration_tutorial = IMU校准教程
|
||||
onboarding-calibration_tutorial-subtitle = 这将有助于减少追踪器漂移!
|
||||
onboarding-calibration_tutorial-description = 每次开启追踪器时,它们都需要在平坦的表面上放置片刻以进行自校准。你也可以通过点击“{ onboarding-calibration_tutorial-calibrate }”按钮来手动校准, <b>校准过程中不要移动追踪器!</b>
|
||||
onboarding-calibration_tutorial-description-v1 = 打开追踪器后,将它们放在稳定的平面上一段时间,以便进行校准。追踪器开机后可随时进行校准 - 本页仅是一个校准教程。首先,点击 “{ onboarding-calibration_tutorial-calibrate }” 按钮,然后 <b>不要移动您的追踪器!</b>
|
||||
onboarding-calibration_tutorial-calibrate = 我已经把追踪器放在桌子上了
|
||||
onboarding-calibration_tutorial-status-waiting = 等待你的操作
|
||||
onboarding-calibration_tutorial-status-calibrating = 校准中
|
||||
@@ -1301,13 +1309,13 @@ onboarding-stay_aligned-preparation-title = 准备
|
||||
onboarding-stay_aligned-preparation-tip = 站直并向前看,双臂放在身体两侧。
|
||||
onboarding-stay_aligned-relaxed_poses-standing-title = 站立放松姿势
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-0 = 1. 以舒适的姿势站立并放松。
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-2 = 3. 按下“检测姿势”按钮。
|
||||
onboarding-stay_aligned-relaxed_poses-standing-step-1-v2 = 2. 按下“保存姿势”按钮。
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-title = 椅子上放松姿势
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-0 = 1. 以舒适的姿势坐下并放松。
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-2 = 3. 按下“检测姿势”按钮。
|
||||
onboarding-stay_aligned-relaxed_poses-sitting-step-1-v2 = 2. 按下“保存姿势”按钮。
|
||||
onboarding-stay_aligned-relaxed_poses-flat-title = 地面/平躺放松姿势
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-0 = 1. 以舒适的姿势坐或躺在地面上,保持腿在前方并放松。
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-2 = 3. 按下“检测姿势”按钮。
|
||||
onboarding-stay_aligned-relaxed_poses-flat-step-1-v2 = 2. 按下“保存姿势”按钮。
|
||||
onboarding-stay_aligned-relaxed_poses-skip_step = 跳过
|
||||
onboarding-stay_aligned-done-title = 持续校准已开启!
|
||||
onboarding-stay_aligned-done-description = 持续校准已设定完成!
|
||||
|
||||
@@ -12,6 +12,13 @@ default-run = "slimevr"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
# The `_lib` suffix may seem redundant but it is necessary
|
||||
# to make the lib name unique and wouldn't conflict with the bin name.
|
||||
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
|
||||
name = "slimevr_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
||||
@@ -22,7 +29,6 @@ custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0", features = [] }
|
||||
cfg_aliases = "0.2"
|
||||
shadow-rs = "0.35"
|
||||
|
||||
[dependencies]
|
||||
@@ -31,7 +37,7 @@ serde = { version = "1", features = ["derive"] }
|
||||
tauri = { version = "2.0", features = ["devtools", "tray-icon", "image-png", "rustls-tls"] }
|
||||
tauri-runtime = "2.0"
|
||||
tauri-plugin-dialog = "2.0"
|
||||
tauri-plugin-fs = "2.0"
|
||||
tauri-plugin-fs = "2.4.1"
|
||||
tauri-plugin-os = "2.0"
|
||||
tauri-plugin-shell = "2.0"
|
||||
tauri-plugin-store = "2.0"
|
||||
@@ -49,7 +55,6 @@ shadow-rs = { version = "0.35", default-features = false }
|
||||
const_format = "0.2.30"
|
||||
cfg-if = "1"
|
||||
color-eyre = "0.6"
|
||||
rfd = { version = "0.15", features = ["gtk3"], default-features = false }
|
||||
dirs-next = "2.0.0"
|
||||
discord-sdk = "0.3.6"
|
||||
tokio = { version = "1.37.0", features = ["time"] }
|
||||
@@ -62,3 +67,6 @@ winreg = "0.52"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
libloading = "0.8"
|
||||
|
||||
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||
rfd = { version = "0.15", features = ["gtk3"], default-features = false }
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use cfg_aliases::cfg_aliases;
|
||||
|
||||
fn main() -> shadow_rs::SdResult<()> {
|
||||
// Bypass for Nix script having libudev-zero and Tauri not liking it
|
||||
if let Some(path) = option_env!("SLIMEVR_RUST_LD_LIBRARY_PATH") {
|
||||
@@ -7,9 +5,5 @@ fn main() -> shadow_rs::SdResult<()> {
|
||||
}
|
||||
|
||||
tauri_build::build();
|
||||
cfg_aliases! {
|
||||
mobile: { any(target_os = "ios", target_os = "android") },
|
||||
desktop: { not(any(target_os = "ios", target_os = "android")) }
|
||||
}
|
||||
shadow_rs::new()
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
</provides>
|
||||
|
||||
<releases>
|
||||
<release version="0.16.2" date="2025-08-01"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.2</url></release>
|
||||
<release version="0.16.1" date="2025-07-27"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.1</url></release>
|
||||
<release version="0.16.1~rc.2" type="development" date="2025-07-17"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.1-rc.2</url></release>
|
||||
<release version="0.16.1~rc.1" type="development" date="2025-07-04"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.1-rc.1</url></release>
|
||||
<release version="0.16.0" date="2025-07-01"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.0</url></release>
|
||||
<release version="0.16.0~rc.2" type="development" date="2025-06-20"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.0-rc.2</url></release>
|
||||
<release version="0.16.0~rc.1" type="development" date="2025-05-27"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.16.0-rc.1</url></release>
|
||||
|
||||
10
gui/src-tauri/gen/.stowrc
Normal file
10
gui/src-tauri/gen/.stowrc
Normal file
@@ -0,0 +1,10 @@
|
||||
--ignore='^gui$'
|
||||
--ignore='^\..+'
|
||||
--ignore='^node_modules$'
|
||||
--ignore='^build$'
|
||||
--ignore='^(local|keystore).properties$'
|
||||
--ignore='^target$'
|
||||
--ignore='^assets'
|
||||
--ignore='.*\.(toml|yaml|nix|lock|json|md)$'
|
||||
-d ../../../../
|
||||
-t android
|
||||
1
gui/src-tauri/gen/android/app
Symbolic link
1
gui/src-tauri/gen/android/app
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../server/android/
|
||||
1
gui/src-tauri/gen/android/build.gradle.kts
Symbolic link
1
gui/src-tauri/gen/android/build.gradle.kts
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/build.gradle.kts
|
||||
1
gui/src-tauri/gen/android/buildSrc
Symbolic link
1
gui/src-tauri/gen/android/buildSrc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/buildSrc
|
||||
1
gui/src-tauri/gen/android/gradle
Symbolic link
1
gui/src-tauri/gen/android/gradle
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/gradle
|
||||
1
gui/src-tauri/gen/android/gradle.properties
Symbolic link
1
gui/src-tauri/gen/android/gradle.properties
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/gradle.properties
|
||||
1
gui/src-tauri/gen/android/gradlew
vendored
Symbolic link
1
gui/src-tauri/gen/android/gradlew
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/gradlew
|
||||
1
gui/src-tauri/gen/android/gradlew.bat
vendored
Symbolic link
1
gui/src-tauri/gen/android/gradlew.bat
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/gradlew.bat
|
||||
1
gui/src-tauri/gen/android/server
Symbolic link
1
gui/src-tauri/gen/android/server
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/server
|
||||
1
gui/src-tauri/gen/android/settings.gradle.kts
Symbolic link
1
gui/src-tauri/gen/android/settings.gradle.kts
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/settings.gradle.kts
|
||||
1
gui/src-tauri/gen/android/solarxr-protocol
Symbolic link
1
gui/src-tauri/gen/android/solarxr-protocol
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/solarxr-protocol
|
||||
1
gui/src-tauri/gen/android/tauri.settings.gradle
Symbolic link
1
gui/src-tauri/gen/android/tauri.settings.gradle
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../SlimeVR-Server/tauri.settings.gradle
|
||||
6
gui/src-tauri/src/cross.rs
Normal file
6
gui/src-tauri/src/cross.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub struct TrayAvailable(pub bool);
|
||||
|
||||
#[tauri::command]
|
||||
pub fn is_tray_available(tray_available: tauri::State<TrayAvailable>) -> bool {
|
||||
tray_available.0
|
||||
}
|
||||
45
gui/src-tauri/src/lib.rs
Normal file
45
gui/src-tauri/src/lib.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use tauri::Manager;
|
||||
|
||||
mod cross;
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
log_panics::init();
|
||||
|
||||
tauri::Builder::default()
|
||||
.plugin(
|
||||
tauri_plugin_log::Builder::new()
|
||||
.target(tauri_plugin_log::Target::new(
|
||||
tauri_plugin_log::TargetKind::LogDir {
|
||||
file_name: Some("slimevr".to_string()),
|
||||
},
|
||||
))
|
||||
.max_file_size(30_000 /* bytes */)
|
||||
.rotation_strategy(tauri_plugin_log::RotationStrategy::KeepSome(3))
|
||||
.build(),
|
||||
)
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_store::Builder::default().build())
|
||||
.plugin(tauri_plugin_http::init())
|
||||
.invoke_handler(tauri::generate_handler![cross::is_tray_available,])
|
||||
.setup(move |app| {
|
||||
log::info!("SlimeVR started!");
|
||||
|
||||
let _ = tauri::WebviewWindowBuilder::new(
|
||||
app,
|
||||
"main",
|
||||
tauri::WebviewUrl::App("index.html".into()),
|
||||
)
|
||||
.build()?;
|
||||
|
||||
app.manage(cross::TrayAvailable(false));
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
@@ -22,6 +22,7 @@ use crate::util::{
|
||||
get_launch_path, show_error, valid_java_paths, Cli, JAVA_BIN, MINIMUM_JAVA_VERSION,
|
||||
};
|
||||
|
||||
mod cross;
|
||||
mod presence;
|
||||
mod state;
|
||||
mod tray;
|
||||
@@ -106,6 +107,7 @@ fn main() -> Result<()> {
|
||||
setup_webview2()?;
|
||||
|
||||
// Check for environment variables that can affect the server, and if so, warn in log and GUI
|
||||
#[cfg(desktop)]
|
||||
check_environment_variables();
|
||||
|
||||
// Spawn server process
|
||||
@@ -189,6 +191,7 @@ fn setup_webview2() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(desktop)]
|
||||
fn check_environment_variables() {
|
||||
use itertools::Itertools;
|
||||
const ENVS_TO_CHECK: &[&str] = &["_JAVA_OPTIONS", "JAVA_TOOL_OPTIONS"];
|
||||
@@ -264,7 +267,7 @@ fn setup_tauri(
|
||||
open_logs_folder,
|
||||
tray::update_translations,
|
||||
tray::update_tray_text,
|
||||
tray::is_tray_available,
|
||||
cross::is_tray_available,
|
||||
presence::discord_client_exists,
|
||||
presence::update_presence,
|
||||
presence::clear_presence,
|
||||
@@ -299,7 +302,7 @@ fn setup_tauri(
|
||||
tray::create_tray(handle)?;
|
||||
presence::create_presence(handle)?;
|
||||
} else {
|
||||
app.manage(tray::TrayAvailable(false));
|
||||
app.manage(cross::TrayAvailable(false));
|
||||
}
|
||||
|
||||
app.manage(Mutex::new(window_state));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::{collections::HashMap, sync::Mutex};
|
||||
|
||||
use crate::cross::TrayAvailable;
|
||||
use tauri::{
|
||||
include_image,
|
||||
menu::{Menu, MenuBuilder, MenuItemBuilder, MenuItemKind},
|
||||
@@ -8,7 +9,6 @@ use tauri::{
|
||||
};
|
||||
|
||||
pub struct TrayMenu<R: Runtime>(Menu<R>);
|
||||
pub struct TrayAvailable(pub bool);
|
||||
|
||||
pub struct TrayTranslations {
|
||||
store: Mutex<HashMap<String, String>>,
|
||||
@@ -22,11 +22,6 @@ impl TrayTranslations {
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn is_tray_available(tray_available: State<TrayAvailable>) -> bool {
|
||||
tray_available.0
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn update_translations<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
|
||||
6
gui/src-tauri/tauri.android.conf.json
Normal file
6
gui/src-tauri/tauri.android.conf.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm run start --host"
|
||||
},
|
||||
"identifier": "dev.slimevr.android"
|
||||
}
|
||||
@@ -55,6 +55,16 @@ export function WidgetsComponent() {
|
||||
<ResetButton type={ResetType.Yaw} size="big"></ResetButton>
|
||||
<ResetButton type={ResetType.Full} size="big"></ResetButton>
|
||||
<ResetButton type={ResetType.Mounting} size="big"></ResetButton>
|
||||
<ResetButton
|
||||
type={ResetType.Mounting}
|
||||
size="big"
|
||||
bodyPartsToReset="feet"
|
||||
></ResetButton>
|
||||
<ResetButton
|
||||
type={ResetType.Mounting}
|
||||
size="big"
|
||||
bodyPartsToReset="fingers"
|
||||
></ResetButton>
|
||||
<ClearMountingButton></ClearMountingButton>
|
||||
{(typeof __ANDROID__ === 'undefined' || !__ANDROID__?.isThere()) && (
|
||||
<BVHButton></BVHButton>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
BodyPart,
|
||||
ResetRequestT,
|
||||
ResetType,
|
||||
RpcMessage,
|
||||
@@ -22,16 +23,20 @@ import {
|
||||
} from '@/components/commons/icon/ResetIcon';
|
||||
import { useStatusContext } from '@/hooks/status-system';
|
||||
import classNames from 'classnames';
|
||||
import { FootIcon } from '@/components/commons/icon/FootIcon';
|
||||
import { FingersIcon } from '@/components/commons/icon/FingersIcon';
|
||||
|
||||
export function ResetButton({
|
||||
type,
|
||||
size = 'big',
|
||||
bodyPartsToReset = 'default',
|
||||
className,
|
||||
onReseted,
|
||||
}: {
|
||||
className?: string;
|
||||
type: ResetType;
|
||||
size: 'big' | 'small';
|
||||
bodyPartsToReset?: 'default' | 'feet' | 'fingers';
|
||||
onReseted?: () => void;
|
||||
}) {
|
||||
const { l10n } = useLocalization();
|
||||
@@ -50,9 +55,55 @@ export function ResetButton({
|
||||
[statuses]
|
||||
);
|
||||
|
||||
const feetBodyParts = [BodyPart.LEFT_FOOT, BodyPart.RIGHT_FOOT];
|
||||
const fingerBodyParts = [
|
||||
BodyPart.LEFT_THUMB_METACARPAL,
|
||||
BodyPart.LEFT_THUMB_PROXIMAL,
|
||||
BodyPart.LEFT_THUMB_DISTAL,
|
||||
BodyPart.LEFT_INDEX_PROXIMAL,
|
||||
BodyPart.LEFT_INDEX_INTERMEDIATE,
|
||||
BodyPart.LEFT_INDEX_DISTAL,
|
||||
BodyPart.LEFT_MIDDLE_PROXIMAL,
|
||||
BodyPart.LEFT_MIDDLE_INTERMEDIATE,
|
||||
BodyPart.LEFT_MIDDLE_DISTAL,
|
||||
BodyPart.LEFT_RING_PROXIMAL,
|
||||
BodyPart.LEFT_RING_INTERMEDIATE,
|
||||
BodyPart.LEFT_RING_DISTAL,
|
||||
BodyPart.LEFT_LITTLE_PROXIMAL,
|
||||
BodyPart.LEFT_LITTLE_INTERMEDIATE,
|
||||
BodyPart.LEFT_LITTLE_DISTAL,
|
||||
BodyPart.RIGHT_THUMB_METACARPAL,
|
||||
BodyPart.RIGHT_THUMB_PROXIMAL,
|
||||
BodyPart.RIGHT_THUMB_DISTAL,
|
||||
BodyPart.RIGHT_INDEX_PROXIMAL,
|
||||
BodyPart.RIGHT_INDEX_INTERMEDIATE,
|
||||
BodyPart.RIGHT_INDEX_DISTAL,
|
||||
BodyPart.RIGHT_MIDDLE_PROXIMAL,
|
||||
BodyPart.RIGHT_MIDDLE_INTERMEDIATE,
|
||||
BodyPart.RIGHT_MIDDLE_DISTAL,
|
||||
BodyPart.RIGHT_RING_PROXIMAL,
|
||||
BodyPart.RIGHT_RING_INTERMEDIATE,
|
||||
BodyPart.RIGHT_RING_DISTAL,
|
||||
BodyPart.RIGHT_LITTLE_PROXIMAL,
|
||||
BodyPart.RIGHT_LITTLE_INTERMEDIATE,
|
||||
BodyPart.RIGHT_LITTLE_DISTAL,
|
||||
];
|
||||
|
||||
const reset = () => {
|
||||
const req = new ResetRequestT();
|
||||
req.resetType = type;
|
||||
switch (bodyPartsToReset) {
|
||||
case 'default':
|
||||
// Server handles it. Usually all body parts except fingers.
|
||||
req.bodyParts = [];
|
||||
break;
|
||||
case 'feet':
|
||||
req.bodyParts = feetBodyParts;
|
||||
break;
|
||||
case 'fingers':
|
||||
req.bodyParts = fingerBodyParts;
|
||||
break;
|
||||
}
|
||||
sendRPCPacket(RpcMessage.ResetRequest, req);
|
||||
};
|
||||
|
||||
@@ -75,20 +126,36 @@ export function ResetButton({
|
||||
const text = useMemo(() => {
|
||||
switch (type) {
|
||||
case ResetType.Yaw:
|
||||
return l10n.getString('reset-yaw');
|
||||
return l10n.getString(
|
||||
'reset-yaw' +
|
||||
(bodyPartsToReset !== 'default' ? '-' + bodyPartsToReset : '')
|
||||
);
|
||||
case ResetType.Mounting:
|
||||
return l10n.getString('reset-mounting');
|
||||
return l10n.getString(
|
||||
'reset-mounting' +
|
||||
(bodyPartsToReset !== 'default' ? '-' + bodyPartsToReset : '')
|
||||
);
|
||||
case ResetType.Full:
|
||||
return l10n.getString('reset-full');
|
||||
return l10n.getString(
|
||||
'reset-full' +
|
||||
(bodyPartsToReset !== 'default' ? '-' + bodyPartsToReset : '')
|
||||
);
|
||||
}
|
||||
}, [type]);
|
||||
}, [type, bodyPartsToReset]);
|
||||
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case ResetType.Yaw:
|
||||
return <YawResetIcon width={20} />;
|
||||
case ResetType.Mounting:
|
||||
return <MountingResetIcon width={20} />;
|
||||
switch (bodyPartsToReset) {
|
||||
case 'default':
|
||||
return <MountingResetIcon width={20} />;
|
||||
case 'feet':
|
||||
return <FootIcon width={30} />;
|
||||
case 'fingers':
|
||||
return <FingersIcon width={20} />;
|
||||
}
|
||||
}
|
||||
return <FullResetIcon width={20} />;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { RpcMessage, SkeletonResetAllRequestT } from 'solarxr-protocol';
|
||||
import { Button } from '@/components/commons/Button';
|
||||
import { Typography } from '@/components/commons/Typography';
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { useWebsocketAPI } from '@/hooks/websocket-api';
|
||||
import { useLocalization } from '@fluent/react';
|
||||
import { RpcMessage, SkeletonResetAllRequestT } from 'solarxr-protocol';
|
||||
|
||||
export function ResetProportionsStep({
|
||||
nextStep,
|
||||
@@ -43,7 +43,7 @@ export function ResetProportionsStep({
|
||||
{l10n.getString('onboarding-automatic_proportions-prev_step')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
sendRPCPacket(
|
||||
RpcMessage.SkeletonResetAllRequest,
|
||||
|
||||
@@ -868,7 +868,7 @@ export function GeneralSettings() {
|
||||
<div className="flex flex-col pt-2 pb-3">
|
||||
<Typography color="secondary">
|
||||
{l10n.getString(
|
||||
'settings-general-fk_settings-leg_fk-reset_mounting_feet-description'
|
||||
'settings-general-fk_settings-leg_fk-reset_mounting_feet-description-v1'
|
||||
)}
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -879,7 +879,7 @@ export function GeneralSettings() {
|
||||
control={control}
|
||||
name="resetsSettings.resetMountingFeet"
|
||||
label={l10n.getString(
|
||||
'settings-general-fk_settings-leg_fk-reset_mounting_feet'
|
||||
'settings-general-fk_settings-leg_fk-reset_mounting_feet-v1'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -114,6 +114,13 @@ export function Serial() {
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (consoleRef.current)
|
||||
consoleRef.current.scrollTo({
|
||||
top: consoleRef.current.scrollHeight,
|
||||
});
|
||||
}, [consoleContent]);
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => {
|
||||
if (!isSerialOpen) {
|
||||
@@ -241,7 +248,7 @@ export function Serial() {
|
||||
</div>
|
||||
<div className="bg-background-80 rounded-lg flex-grow h-0 flex flex-col p-2">
|
||||
<div
|
||||
className="flex-grow overflow-auto overscroll-y-contain snap-y snap-proximity"
|
||||
className="flex-grow overflow-x-auto overflow-y-auto"
|
||||
ref={consoleRef}
|
||||
>
|
||||
<div className="flex select-text">
|
||||
@@ -251,7 +258,6 @@ export function Serial() {
|
||||
: l10n.getString('settings-serial-connection_lost')}
|
||||
</pre>
|
||||
</div>
|
||||
<div className="snap-end" />
|
||||
</div>
|
||||
<div className="border-t-2 pt-2 border-background-60 border-solid gap-2 flex flex-row">
|
||||
<div className="xs:flex flex-grow xs:flex-wrap gap-2 grid grid-cols-2">
|
||||
|
||||
@@ -101,7 +101,7 @@ export async function fetchCurrentFirmwareRelease(): Promise<FirmwareRelease | n
|
||||
name: release.name,
|
||||
version,
|
||||
changelog: release.body,
|
||||
firmwareFile: fwAsset,
|
||||
firmwareFile: fwAsset.browser_download_url,
|
||||
userCanUpdate,
|
||||
});
|
||||
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -60,8 +60,8 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
'@tauri-apps/plugin-fs':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
specifier: 2.4.1
|
||||
version: 2.4.1
|
||||
'@tauri-apps/plugin-http':
|
||||
specifier: ^2.5.0
|
||||
version: 2.5.0
|
||||
@@ -1254,8 +1254,8 @@ packages:
|
||||
'@tauri-apps/plugin-dialog@2.0.0':
|
||||
resolution: {integrity: sha512-ApNkejXP2jpPBSifznPPcHTXxu9/YaRW+eJ+8+nYwqp0lLUtebFHG4QhxitM43wwReHE81WAV1DQ/b+2VBftOA==}
|
||||
|
||||
'@tauri-apps/plugin-fs@2.0.0':
|
||||
resolution: {integrity: sha512-BNEeQQ5aH8J5SwYuWgRszVyItsmquRuzK2QRkVj8Z0sCsLnSvJFYI3JHRzzr3ltZGq1nMPtblrlZzuKqVzRawA==}
|
||||
'@tauri-apps/plugin-fs@2.4.1':
|
||||
resolution: {integrity: sha512-vJlKZVGF3UAFGoIEVT6Oq5L4HGDCD78WmA4uhzitToqYiBKWAvZR61M6zAyQzHqLs0ADemkE4RSy/5sCmZm6ZQ==}
|
||||
|
||||
'@tauri-apps/plugin-http@2.5.0':
|
||||
resolution: {integrity: sha512-l4M2DUIsOBIMrbj4dJZwrB4mJiB7OA/2Tj3gEbX2fjq5MOpETklJPKfDvzUTDwuq4lIKCKKykz8E8tpOgvi0EQ==}
|
||||
@@ -5464,9 +5464,9 @@ snapshots:
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.0.2
|
||||
|
||||
'@tauri-apps/plugin-fs@2.0.0':
|
||||
'@tauri-apps/plugin-fs@2.4.1':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.0.2
|
||||
'@tauri-apps/api': 2.6.0
|
||||
|
||||
'@tauri-apps/plugin-http@2.5.0':
|
||||
dependencies:
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
channel = "1.82"
|
||||
profile = "default"
|
||||
components = ["rustc", "cargo", "clippy", "rustfmt", "rust-analyzer", "rust-src"]
|
||||
targets = ["x86_64-linux-android", "aarch64-linux-android", "armv7-linux-androideabi", "i686-linux-android"]
|
||||
|
||||
7
server/android/.gitignore
vendored
7
server/android/.gitignore
vendored
@@ -1,2 +1,9 @@
|
||||
/build
|
||||
/src/main/resources/web-gui
|
||||
|
||||
/src/main/java/dev/slimevr/android/generated
|
||||
/src/main/jniLibs/**/*.so
|
||||
/src/main/assets/tauri.conf.json
|
||||
/tauri.build.gradle.kts
|
||||
/proguard-tauri.pro
|
||||
/tauri.properties
|
||||
|
||||
@@ -7,14 +7,24 @@
|
||||
*/
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import java.io.FileInputStream
|
||||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
kotlin("android")
|
||||
kotlin("plugin.serialization")
|
||||
id("com.github.gmazzo.buildconfig")
|
||||
|
||||
id("com.android.application") version "8.6.1"
|
||||
id("com.android.application")
|
||||
id("org.ajoberstar.grgit")
|
||||
id("rust")
|
||||
}
|
||||
|
||||
val tauriProperties = Properties().apply {
|
||||
val propFile = file("tauri.properties")
|
||||
if (propFile.exists()) {
|
||||
propFile.inputStream().use { load(it) }
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
@@ -28,17 +38,6 @@ java {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<Copy>("copyGuiAssets") {
|
||||
from(rootProject.layout.projectDirectory.dir("gui/dist"))
|
||||
into(layout.projectDirectory.dir("src/main/resources/web-gui"))
|
||||
if (inputs.sourceFiles.isEmpty) {
|
||||
throw GradleException("You need to run \"pnpm run build\" on the gui folder first!")
|
||||
}
|
||||
}
|
||||
tasks.preBuild {
|
||||
dependsOn(":server:android:copyGuiAssets")
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
@@ -61,6 +60,14 @@ repositories {
|
||||
google()
|
||||
}
|
||||
|
||||
rust {
|
||||
rootDirRel = if (projectDir.absolutePath.contains("gen/android")) {
|
||||
"../../../../../"
|
||||
} else {
|
||||
"../../gui/src-tauri"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":server:core"))
|
||||
|
||||
@@ -68,17 +75,15 @@ dependencies {
|
||||
implementation("org.apache.commons:commons-lang3:3.15.0")
|
||||
|
||||
// Android stuff
|
||||
implementation("androidx.appcompat:appcompat:1.7.0")
|
||||
implementation("androidx.webkit:webkit:1.14.0")
|
||||
implementation("androidx.appcompat:appcompat:1.7.1")
|
||||
implementation("androidx.activity:activity-ktx:1.10.1")
|
||||
implementation("androidx.core:core-ktx:1.13.1")
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
||||
androidTestImplementation("androidx.test.ext:junit:1.2.1")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
|
||||
// For hosting web GUI
|
||||
implementation("io.ktor:ktor-server-core:2.3.12")
|
||||
implementation("io.ktor:ktor-server-netty:2.3.10")
|
||||
implementation("io.ktor:ktor-server-caching-headers:2.3.12")
|
||||
|
||||
// Serial
|
||||
implementation("com.github.mik3y:usb-serial-for-android:3.7.0")
|
||||
@@ -90,34 +95,18 @@ extra.apply {
|
||||
set("gitVersionName", grgit.describe(mapOf("tags" to true, "always" to true)))
|
||||
}
|
||||
android {
|
||||
// The app's namespace. Used primarily to access app resources.
|
||||
|
||||
namespace = "dev.slimevr.android"
|
||||
|
||||
/* compileSdk specifies the Android API level Gradle should use to
|
||||
compile your app. This means your app can use the API features included in
|
||||
this API level and lower. */
|
||||
|
||||
compileSdk = 35
|
||||
|
||||
/* The defaultConfig block encapsulates default settings and entries for all
|
||||
build variants and can override some attributes in main/AndroidManifest.xml
|
||||
dynamically from the build system. You can configure product flavors to override
|
||||
these values for different versions of your app. */
|
||||
|
||||
packaging {
|
||||
resources.excludes.add("META-INF/*")
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
|
||||
// Uniquely identifies the package for publishing.
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "false"
|
||||
applicationId = "dev.slimevr.server.android"
|
||||
|
||||
// Defines the minimum API level required to run the app.
|
||||
minSdk = 26
|
||||
|
||||
// Specifies the API level used to test the app.
|
||||
targetSdk = 35
|
||||
|
||||
// adds an offset of the version code as we might do apk releases in the middle of actual
|
||||
@@ -128,8 +117,27 @@ android {
|
||||
|
||||
// Defines a user-friendly version name for your app.
|
||||
versionName = extra["gitVersionName"] as? String ?: "v0.0.0"
|
||||
setProperty("archivesBaseName", "app")
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
ndk {
|
||||
abiFilters += listOf("x86", "x86_64", "arm64-v8a", "armeabi-v7a")
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
keyAlias = keystoreProperties["keyAlias"] as String?
|
||||
keyPassword = keystoreProperties["password"] as String?
|
||||
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
|
||||
storePassword = keystoreProperties["password"] as String?
|
||||
}
|
||||
}
|
||||
|
||||
/* The buildTypes block is where you can configure multiple build types.
|
||||
@@ -139,15 +147,25 @@ android {
|
||||
build type applies ProGuard settings and is not signed by default. */
|
||||
|
||||
buildTypes {
|
||||
|
||||
/* By default, Android Studio configures the release build type to enable code
|
||||
shrinking, using minifyEnabled, and specifies the default ProGuard rules file. */
|
||||
|
||||
getByName("debug") {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
packaging {
|
||||
jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
|
||||
}
|
||||
}
|
||||
getByName("release") {
|
||||
isMinifyEnabled = true // Enables code shrinking for the release build type.
|
||||
isMinifyEnabled = true
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android.txt"),
|
||||
"proguard-rules.pro",
|
||||
*fileTree(".") { include("**/*.pro") }
|
||||
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
|
||||
.toList().toTypedArray(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -159,4 +177,13 @@ android {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
apply(from = "tauri.build.gradle.kts")
|
||||
} catch (e: Exception) {
|
||||
println("Couldn't enable tauri stuff")
|
||||
}
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name=".ForegroundService"
|
||||
|
||||
@@ -9,17 +9,7 @@ import dev.slimevr.Keybinding
|
||||
import dev.slimevr.VRServer
|
||||
import dev.slimevr.android.serial.AndroidSerialHandler
|
||||
import io.eiren.util.logging.LogManager
|
||||
import io.ktor.http.CacheControl
|
||||
import io.ktor.http.CacheControl.Visibility
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.engine.embeddedServer
|
||||
import io.ktor.server.http.content.CachingOptions
|
||||
import io.ktor.server.http.content.staticResources
|
||||
import io.ktor.server.netty.Netty
|
||||
import io.ktor.server.plugins.cachingheaders.CachingHeaders
|
||||
import io.ktor.server.routing.routing
|
||||
import java.io.File
|
||||
import java.time.ZonedDateTime
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -29,18 +19,6 @@ val vrServerInitialized: Boolean
|
||||
get() = ::vrServer.isInitialized
|
||||
|
||||
fun main(activity: AppCompatActivity) {
|
||||
// Host the web GUI server
|
||||
embeddedServer(Netty, port = 34536) {
|
||||
routing {
|
||||
install(CachingHeaders) {
|
||||
options { _, _ ->
|
||||
CachingOptions(CacheControl.NoStore(Visibility.Public), ZonedDateTime.now())
|
||||
}
|
||||
}
|
||||
staticResources("/", "web-gui", "index.html")
|
||||
}
|
||||
}.start(wait = false)
|
||||
|
||||
thread(start = true, name = "Main VRServer Thread") {
|
||||
try {
|
||||
LogManager.initialize(activity.filesDir)
|
||||
|
||||
@@ -3,9 +3,7 @@ package dev.slimevr.android
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import io.eiren.util.logging.LogManager
|
||||
|
||||
class AndroidJsObject {
|
||||
@@ -13,10 +11,10 @@ class AndroidJsObject {
|
||||
fun isThere(): Boolean = true
|
||||
}
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
class MainActivity : TauriActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
// Initialize logger (doesn't re-initialize if already run)
|
||||
try {
|
||||
@@ -33,35 +31,6 @@ class MainActivity : AppCompatActivity() {
|
||||
LogManager.info("[MainActivity] VRServer is already running, skipping initialization.")
|
||||
}
|
||||
|
||||
// Load the web GUI web page
|
||||
LogManager.info("[MainActivity] Initializing GUI WebView...")
|
||||
val guiWebView = findViewById<WebView>(R.id.guiWebView)
|
||||
|
||||
// ## Configure for web GUI ##
|
||||
// Enable debug mode
|
||||
WebView.setWebContentsDebuggingEnabled(true)
|
||||
|
||||
// Set required features
|
||||
guiWebView.settings.javaScriptEnabled = true
|
||||
guiWebView.settings.domStorageEnabled = true
|
||||
|
||||
// TODO: Let code know it is in android, should be gone when we start using tauri
|
||||
guiWebView.addJavascriptInterface(AndroidJsObject(), "__ANDROID__")
|
||||
|
||||
// Try fixing zoom usability
|
||||
guiWebView.settings.setSupportZoom(true)
|
||||
guiWebView.settings.useWideViewPort = true
|
||||
guiWebView.settings.loadWithOverviewMode = true
|
||||
guiWebView.invokeZoomPicker()
|
||||
|
||||
// Disable cache! This is all local anyway
|
||||
guiWebView.settings.cacheMode = WebSettings.LOAD_NO_CACHE
|
||||
guiWebView.clearCache(true)
|
||||
|
||||
// Load GUI page
|
||||
guiWebView.loadUrl("http://127.0.0.1:34536/")
|
||||
LogManager.info("[MainActivity] GUI WebView has been initialized and loaded.")
|
||||
|
||||
// Start a foreground service to notify the user the SlimeVR Server is running
|
||||
// This also helps prevent Android from ejecting the process unexpectedly
|
||||
val serviceIntent = Intent(this, ForegroundService::class.java)
|
||||
|
||||
5
server/android/src/main/res/xml/file_paths.xml
Normal file
5
server/android/src/main/res/xml/file_paths.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<external-path name="my_images" path="." />
|
||||
<cache-path name="my_cache_images" path="." />
|
||||
</paths>
|
||||
@@ -40,6 +40,7 @@ import java.util.*
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.function.Consumer
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.concurrent.schedule
|
||||
|
||||
typealias BridgeProvider = (
|
||||
@@ -297,16 +298,16 @@ class VRServer @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun resetTrackersFull(resetSourceName: String?) {
|
||||
queueTask { humanPoseManager.resetTrackersFull(resetSourceName) }
|
||||
fun resetTrackersFull(resetSourceName: String?, bodyParts: List<Int> = ArrayList()) {
|
||||
queueTask { humanPoseManager.resetTrackersFull(resetSourceName, bodyParts) }
|
||||
}
|
||||
|
||||
fun resetTrackersYaw(resetSourceName: String?) {
|
||||
queueTask { humanPoseManager.resetTrackersYaw(resetSourceName) }
|
||||
fun resetTrackersYaw(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
|
||||
queueTask { humanPoseManager.resetTrackersYaw(resetSourceName, bodyParts) }
|
||||
}
|
||||
|
||||
fun resetTrackersMounting(resetSourceName: String?) {
|
||||
queueTask { humanPoseManager.resetTrackersMounting(resetSourceName) }
|
||||
fun resetTrackersMounting(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
|
||||
queueTask { humanPoseManager.resetTrackersMounting(resetSourceName, bodyParts) }
|
||||
}
|
||||
|
||||
fun clearTrackersMounting(resetSourceName: String?) {
|
||||
|
||||
@@ -31,7 +31,7 @@ enum class ArmsResetModes(val id: Int) {
|
||||
|
||||
class ResetsConfig {
|
||||
|
||||
// Enable mounting reset for feet?
|
||||
// Always reset mounting for feet
|
||||
var resetMountingFeet = false
|
||||
|
||||
// Reset mode used for the arms
|
||||
|
||||
@@ -351,9 +351,37 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
|
||||
fun onResetRequest(conn: GenericConnection, messageHeader: RpcMessageHeader) {
|
||||
val req = messageHeader.message(ResetRequest()) as? ResetRequest ?: return
|
||||
|
||||
if (req.resetType() == ResetType.Yaw) api.server.resetTrackersYaw(RESET_SOURCE_NAME)
|
||||
if (req.resetType() == ResetType.Full) api.server.resetTrackersFull(RESET_SOURCE_NAME)
|
||||
if (req.resetType() == ResetType.Mounting) api.server.resetTrackersMounting(RESET_SOURCE_NAME)
|
||||
// Get the list of bodyparts we want to reset
|
||||
// If empty, check in HumanSkeleton will reset all
|
||||
val bodyParts = mutableListOf<Int>()
|
||||
if (req.bodyPartsLength() > 0) {
|
||||
val buffer = req.bodyPartsAsByteBuffer()
|
||||
while (buffer.hasRemaining()) {
|
||||
bodyParts.add(buffer.get().toInt())
|
||||
}
|
||||
}
|
||||
|
||||
if (req.resetType() == ResetType.Yaw) {
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.resetTrackersYaw(RESET_SOURCE_NAME)
|
||||
} else {
|
||||
api.server.resetTrackersYaw(RESET_SOURCE_NAME, bodyParts.toList())
|
||||
}
|
||||
}
|
||||
if (req.resetType() == ResetType.Full) {
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.resetTrackersFull(RESET_SOURCE_NAME)
|
||||
} else {
|
||||
api.server.resetTrackersFull(RESET_SOURCE_NAME, bodyParts.toList())
|
||||
}
|
||||
}
|
||||
if (req.resetType() == ResetType.Mounting) {
|
||||
if (bodyParts.isEmpty()) {
|
||||
api.server.resetTrackersMounting(RESET_SOURCE_NAME)
|
||||
} else {
|
||||
api.server.resetTrackersMounting(RESET_SOURCE_NAME, bodyParts.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onClearMountingResetRequest(
|
||||
|
||||
@@ -10,10 +10,7 @@ import dev.slimevr.tracking.processor.config.SkeletonConfigOffsets
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigToggles
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigValues
|
||||
import dev.slimevr.tracking.processor.skeleton.HumanSkeleton
|
||||
import dev.slimevr.tracking.trackers.Tracker
|
||||
import dev.slimevr.tracking.trackers.TrackerPosition
|
||||
import dev.slimevr.tracking.trackers.TrackerRole
|
||||
import dev.slimevr.tracking.trackers.TrackerStatus
|
||||
import dev.slimevr.tracking.trackers.*
|
||||
import dev.slimevr.trackingpause.TrackingPauseHandler
|
||||
import dev.slimevr.util.ann.VRServerThread
|
||||
import io.eiren.util.ann.ThreadSafe
|
||||
@@ -482,8 +479,9 @@ class HumanPoseManager(val server: VRServer?) {
|
||||
skeletonConfigManager.computeNodeOffset(node)
|
||||
}
|
||||
|
||||
fun resetTrackersFull(resetSourceName: String?) {
|
||||
skeleton.resetTrackersFull(resetSourceName)
|
||||
@JvmOverloads
|
||||
fun resetTrackersFull(resetSourceName: String?, bodyParts: List<Int> = ArrayList()) {
|
||||
skeleton.resetTrackersFull(resetSourceName, bodyParts)
|
||||
if (server != null) {
|
||||
if (skeleton.headTracker == null && skeleton.neckTracker == null) {
|
||||
server.vrcOSCHandler.yawAlign(IDENTITY)
|
||||
@@ -498,8 +496,9 @@ class HumanPoseManager(val server: VRServer?) {
|
||||
}
|
||||
}
|
||||
|
||||
fun resetTrackersYaw(resetSourceName: String?) {
|
||||
skeleton.resetTrackersYaw(resetSourceName)
|
||||
@JvmOverloads
|
||||
fun resetTrackersYaw(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
|
||||
skeleton.resetTrackersYaw(resetSourceName, bodyParts)
|
||||
if (server != null) {
|
||||
if (skeleton.headTracker == null && skeleton.neckTracker == null) {
|
||||
server.vrcOSCHandler.yawAlign(IDENTITY)
|
||||
@@ -571,8 +570,9 @@ class HumanPoseManager(val server: VRServer?) {
|
||||
}
|
||||
}
|
||||
|
||||
fun resetTrackersMounting(resetSourceName: String?) {
|
||||
skeleton.resetTrackersMounting(resetSourceName)
|
||||
@JvmOverloads
|
||||
fun resetTrackersMounting(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
|
||||
skeleton.resetTrackersMounting(resetSourceName, bodyParts)
|
||||
}
|
||||
|
||||
fun clearTrackersMounting(resetSourceName: String?) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import dev.slimevr.tracking.processor.stayaligned.trackers.TrackerSkeleton
|
||||
import dev.slimevr.tracking.trackers.Tracker
|
||||
import dev.slimevr.tracking.trackers.TrackerPosition
|
||||
import dev.slimevr.tracking.trackers.TrackerRole
|
||||
import dev.slimevr.tracking.trackers.TrackerUtils
|
||||
import dev.slimevr.tracking.trackers.TrackerUtils.getFirstAvailableTracker
|
||||
import dev.slimevr.tracking.trackers.TrackerUtils.getTrackerForSkeleton
|
||||
import dev.slimevr.tracking.trackers.udp.TrackerDataType
|
||||
@@ -29,6 +30,7 @@ import io.github.axisangles.ktmath.Vector3
|
||||
import io.github.axisangles.ktmath.Vector3.Companion.NEG_Y
|
||||
import io.github.axisangles.ktmath.Vector3.Companion.NULL
|
||||
import io.github.axisangles.ktmath.Vector3.Companion.POS_Y
|
||||
import solarxr_protocol.datatypes.BodyPart
|
||||
import java.lang.IllegalArgumentException
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@@ -1515,17 +1517,21 @@ class HumanSkeleton(
|
||||
rightLittleDistalTracker,
|
||||
)
|
||||
|
||||
fun resetTrackersFull(resetSourceName: String?) {
|
||||
@JvmOverloads
|
||||
fun resetTrackersFull(resetSourceName: String?, bodyParts: List<Int> = ArrayList()) {
|
||||
var referenceRotation = IDENTITY
|
||||
headTracker?.let {
|
||||
// Always reset the head (ifs in resetsHandler)
|
||||
it.resetsHandler.resetFull(referenceRotation)
|
||||
if (bodyParts.isEmpty() || bodyParts.contains(BodyPart.HEAD)) {
|
||||
// Always reset the head (ifs in resetsHandler)
|
||||
it.resetsHandler.resetFull(referenceRotation)
|
||||
}
|
||||
referenceRotation = it.getRotation()
|
||||
}
|
||||
|
||||
// Resets all axes of the trackers with the HMD as reference.
|
||||
for (tracker in trackersToReset) {
|
||||
// Only reset if tracker needsReset
|
||||
if (tracker != null && (tracker.needsReset || tracker.isHmd)) {
|
||||
if (tracker != null && (tracker.needsReset || tracker.isHmd) && (bodyParts.isEmpty() || bodyParts.contains(tracker.trackerPosition?.bodyPart))) {
|
||||
tracker.resetsHandler.resetFull(referenceRotation)
|
||||
}
|
||||
}
|
||||
@@ -1541,19 +1547,22 @@ class HumanSkeleton(
|
||||
}
|
||||
|
||||
@VRServerThread
|
||||
fun resetTrackersYaw(resetSourceName: String?) {
|
||||
@JvmOverloads
|
||||
fun resetTrackersYaw(resetSourceName: String?, bodyParts: List<Int> = TrackerUtils.allBodyPartsButFingers) {
|
||||
// Resets the yaw of the trackers with the head as reference.
|
||||
var referenceRotation = IDENTITY
|
||||
headTracker?.let {
|
||||
// Only reset if head needsReset and isn't computed
|
||||
if (it.needsReset && !it.isComputed) {
|
||||
it.resetsHandler.resetYaw(referenceRotation)
|
||||
if (bodyParts.isEmpty() || bodyParts.contains(BodyPart.HEAD)) {
|
||||
// Only reset if head needsReset and isn't computed
|
||||
if (it.needsReset && !it.isComputed) {
|
||||
it.resetsHandler.resetYaw(referenceRotation)
|
||||
}
|
||||
}
|
||||
referenceRotation = it.getRotation()
|
||||
}
|
||||
for (tracker in trackersToReset) {
|
||||
// Only reset if tracker needsReset
|
||||
if (tracker != null && tracker.needsReset) {
|
||||
if (tracker != null && tracker.needsReset && (bodyParts.isEmpty() || bodyParts.contains(tracker.trackerPosition?.bodyPart))) {
|
||||
tracker.resetsHandler.resetYaw(referenceRotation)
|
||||
}
|
||||
}
|
||||
@@ -1561,8 +1570,13 @@ class HumanSkeleton(
|
||||
LogManager.info("[HumanSkeleton] Reset: yaw ($resetSourceName)")
|
||||
}
|
||||
|
||||
/**
|
||||
* if bodyParts is empty, this resets mounting for all trackers.
|
||||
* Keep in mind TrackerResetsHandler.kt has some logic as well for which trackers get reset (feet)
|
||||
*/
|
||||
@VRServerThread
|
||||
fun resetTrackersMounting(resetSourceName: String?) {
|
||||
@JvmOverloads
|
||||
fun resetTrackersMounting(resetSourceName: String?, bodyParts: List<Int>) {
|
||||
val trackersToReset = trackersToReset
|
||||
|
||||
// TODO: PLEASE rewrite this handling at some point in the future... This is so
|
||||
@@ -1578,16 +1592,21 @@ class HumanSkeleton(
|
||||
// Resets the mounting orientation of the trackers with the HMD as reference.
|
||||
var referenceRotation = IDENTITY
|
||||
headTracker?.let {
|
||||
// Only reset if head needsMounting or is computed but not HMD
|
||||
if (it.needsMounting || (it.isComputed && !it.isHmd)) {
|
||||
it.resetsHandler.resetMounting(referenceRotation)
|
||||
if (bodyParts.isEmpty() || bodyParts.contains(BodyPart.HEAD)) {
|
||||
// Only reset if head needsMounting or is computed but not HMD
|
||||
if (it.needsMounting || (it.isComputed && !it.isHmd)) {
|
||||
it.resetsHandler.resetMounting(referenceRotation)
|
||||
}
|
||||
}
|
||||
referenceRotation = it.getRotation()
|
||||
}
|
||||
|
||||
// If onlyFeet is true, feet will be forced to be mounting reset in their reset handlers.
|
||||
val onlyFeet = bodyParts.isNotEmpty() && bodyParts.all { it == BodyPart.LEFT_FOOT || it == BodyPart.RIGHT_FOOT }
|
||||
for (tracker in trackersToReset) {
|
||||
// Only reset if tracker needsMounting
|
||||
if (tracker != null && tracker.needsMounting) {
|
||||
tracker.resetsHandler.resetMounting(referenceRotation)
|
||||
if (tracker != null && tracker.needsMounting && (bodyParts.isEmpty() || bodyParts.contains(tracker.trackerPosition?.bodyPart))) {
|
||||
tracker.resetsHandler.resetMounting(referenceRotation, onlyFeet)
|
||||
}
|
||||
}
|
||||
legTweaks.resetBuffer()
|
||||
|
||||
@@ -650,26 +650,30 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
var weightR = getFootPlantWeight(rightFootPosition)
|
||||
|
||||
// if foot trackers exist add to the weights
|
||||
val leftFootYaw = isolateYaw(leftFootRotation)
|
||||
if (leftFootTracker) {
|
||||
weightL *= getRotationalDistanceToPlant(
|
||||
leftFootRotation,
|
||||
leftFootYaw,
|
||||
)
|
||||
}
|
||||
val rightFootYaw = isolateYaw(rightFootRotation)
|
||||
if (rightFootTracker) {
|
||||
weightR *= getRotationalDistanceToPlant(
|
||||
rightFootRotation,
|
||||
rightFootYaw,
|
||||
)
|
||||
}
|
||||
|
||||
// perform the correction
|
||||
leftFootRotation = leftFootRotation
|
||||
.interpR(
|
||||
isolateYaw(leftFootRotation),
|
||||
leftFootYaw,
|
||||
weightL * masterWeightL,
|
||||
)
|
||||
rightFootRotation = rightFootRotation
|
||||
.interpR(
|
||||
isolateYaw(rightFootRotation),
|
||||
rightFootYaw,
|
||||
weightR * masterWeightR,
|
||||
)
|
||||
}
|
||||
@@ -805,8 +809,7 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
}
|
||||
|
||||
// returns the amount to slerp for foot plant when foot trackers are active
|
||||
private fun getRotationalDistanceToPlant(footRot: Quaternion): Float {
|
||||
val footRotYaw: Quaternion = isolateYaw(footRot)
|
||||
private fun getRotationalDistanceToPlant(footRot: Quaternion, footRotYaw: Quaternion): Float {
|
||||
var angle = footRot.angleToR(footRotYaw)
|
||||
angle = (angle / (2 * Math.PI)).toFloat()
|
||||
angle = FastMath.clamp(
|
||||
@@ -1005,12 +1008,9 @@ class LegTweaks(private val skeleton: HumanSkeleton) {
|
||||
}
|
||||
}
|
||||
|
||||
// remove the x and z components of the given quaternion
|
||||
private fun isolateYaw(quaternion: Quaternion): Quaternion = Quaternion(
|
||||
quaternion.w,
|
||||
0f,
|
||||
quaternion.y,
|
||||
0f,
|
||||
// isolate the euler yaw component of a given quaternion
|
||||
private fun isolateYaw(quaternion: Quaternion): Quaternion = Quaternion.rotationAroundYAxis(
|
||||
quaternion.toEulerAngles(EulerOrder.YZX).y,
|
||||
)
|
||||
|
||||
// return a quaternion that has been rotated by the new pitch amount
|
||||
|
||||
@@ -7,6 +7,7 @@ import dev.slimevr.reset.ResetHandler;
|
||||
import dev.slimevr.setup.TapSetupHandler;
|
||||
import dev.slimevr.tracking.processor.HumanPoseManager;
|
||||
import dev.slimevr.tracking.trackers.Tracker;
|
||||
import dev.slimevr.tracking.trackers.TrackerUtils;
|
||||
import solarxr_protocol.rpc.ResetType;
|
||||
import solarxr_protocol.rpc.StatusData;
|
||||
|
||||
@@ -215,7 +216,17 @@ public class TapDetectionManager {
|
||||
&& System.nanoTime() - mountingResetDetector.getDetectionTime()
|
||||
> mountingResetDelayNs
|
||||
) {
|
||||
skeleton.resetTrackersMounting(resetSourceName);
|
||||
// This will ask the skeleton for a mounting reset on every tracker
|
||||
// except fingers.
|
||||
// However, feet being reset or not will end up being decided on a
|
||||
// per-tracker basis
|
||||
// due to the setting being in ResetsConfig.kt
|
||||
skeleton
|
||||
.resetTrackersMounting(
|
||||
resetSourceName,
|
||||
TrackerUtils.INSTANCE.getAllBodyPartsButFingers()
|
||||
);
|
||||
|
||||
mountingResetDetector.resetDetector();
|
||||
mountingResetAllowPlaySound = true;
|
||||
this.resetHandler.sendFinished(ResetType.Mounting);
|
||||
|
||||
@@ -1,8 +1,105 @@
|
||||
@file:Suppress("ktlint:standard:no-wildcard-imports")
|
||||
|
||||
package dev.slimevr.tracking.trackers
|
||||
|
||||
import dev.slimevr.tracking.trackers.TrackerPosition.*
|
||||
import io.github.axisangles.ktmath.Quaternion
|
||||
import solarxr_protocol.datatypes.BodyPart
|
||||
|
||||
fun TrackerPosition?.isThigh(): Boolean {
|
||||
this?.let {
|
||||
return it == LEFT_UPPER_LEG ||
|
||||
it == RIGHT_UPPER_LEG
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isLeftArm(): Boolean {
|
||||
this?.let {
|
||||
return it == LEFT_SHOULDER ||
|
||||
it == LEFT_UPPER_ARM ||
|
||||
it == LEFT_LOWER_ARM ||
|
||||
it == LEFT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isRightArm(): Boolean {
|
||||
this?.let {
|
||||
return it == RIGHT_SHOULDER ||
|
||||
it == RIGHT_UPPER_ARM ||
|
||||
it == RIGHT_LOWER_ARM ||
|
||||
it == RIGHT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isLeftLowerArm(): Boolean {
|
||||
this?.let {
|
||||
return it == LEFT_LOWER_ARM ||
|
||||
it == LEFT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isRightLowerArm(): Boolean {
|
||||
this?.let {
|
||||
return it == RIGHT_LOWER_ARM ||
|
||||
it == RIGHT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isFoot(): Boolean {
|
||||
this?.let {
|
||||
return it == LEFT_FOOT ||
|
||||
it == RIGHT_FOOT
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isLeftFinger(): Boolean {
|
||||
this?.let {
|
||||
return it == LEFT_THUMB_METACARPAL ||
|
||||
it == LEFT_THUMB_PROXIMAL ||
|
||||
it == LEFT_THUMB_DISTAL ||
|
||||
it == LEFT_INDEX_PROXIMAL ||
|
||||
it == LEFT_INDEX_INTERMEDIATE ||
|
||||
it == LEFT_INDEX_DISTAL ||
|
||||
it == LEFT_MIDDLE_PROXIMAL ||
|
||||
it == LEFT_MIDDLE_INTERMEDIATE ||
|
||||
it == LEFT_MIDDLE_DISTAL ||
|
||||
it == LEFT_RING_PROXIMAL ||
|
||||
it == LEFT_RING_INTERMEDIATE ||
|
||||
it == LEFT_RING_DISTAL ||
|
||||
it == LEFT_LITTLE_PROXIMAL ||
|
||||
it == LEFT_LITTLE_INTERMEDIATE ||
|
||||
it == LEFT_LITTLE_DISTAL
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun TrackerPosition?.isRightFinger(): Boolean {
|
||||
this?.let {
|
||||
return it == RIGHT_THUMB_METACARPAL ||
|
||||
it == RIGHT_THUMB_PROXIMAL ||
|
||||
it == RIGHT_THUMB_DISTAL ||
|
||||
it == RIGHT_INDEX_PROXIMAL ||
|
||||
it == RIGHT_INDEX_INTERMEDIATE ||
|
||||
it == RIGHT_INDEX_DISTAL ||
|
||||
it == RIGHT_MIDDLE_PROXIMAL ||
|
||||
it == RIGHT_MIDDLE_INTERMEDIATE ||
|
||||
it == RIGHT_MIDDLE_DISTAL ||
|
||||
it == RIGHT_RING_PROXIMAL ||
|
||||
it == RIGHT_RING_INTERMEDIATE ||
|
||||
it == RIGHT_RING_DISTAL ||
|
||||
it == RIGHT_LITTLE_PROXIMAL ||
|
||||
it == RIGHT_LITTLE_INTERMEDIATE ||
|
||||
it == RIGHT_LITTLE_DISTAL
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a position on the body that a tracker could be placed. Any bone is
|
||||
* a valid position.
|
||||
|
||||
@@ -258,9 +258,9 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
}
|
||||
|
||||
// Adjust for T-Pose (down)
|
||||
tposeDownFix = if (((isLeftArmTracker() || isLeftFingerTracker()) && armsResetMode == ArmsResetModes.TPOSE_DOWN)) {
|
||||
tposeDownFix = if (((tracker.trackerPosition.isLeftArm() || tracker.trackerPosition.isLeftFinger()) && armsResetMode == ArmsResetModes.TPOSE_DOWN)) {
|
||||
EulerAngles(EulerOrder.YZX, 0f, 0f, -FastMath.HALF_PI).toQuaternion()
|
||||
} else if (((isRightArmTracker() || isRightFingerTracker()) && armsResetMode == ArmsResetModes.TPOSE_DOWN)) {
|
||||
} else if (((tracker.trackerPosition.isRightArm() || tracker.trackerPosition.isRightFinger()) && armsResetMode == ArmsResetModes.TPOSE_DOWN)) {
|
||||
EulerAngles(EulerOrder.YZX, 0f, 0f, FastMath.HALF_PI).toQuaternion()
|
||||
} else {
|
||||
Quaternion.IDENTITY
|
||||
@@ -393,15 +393,16 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
/**
|
||||
* Perform the math to align the tracker to go forward
|
||||
* and stores it in mountRotFix, and adjusts yawFix
|
||||
* If forceFeet is true, always reset feet regardless of resetMountingFeet's value.
|
||||
*/
|
||||
fun resetMounting(reference: Quaternion) {
|
||||
fun resetMounting(reference: Quaternion, forceFeet: Boolean = false) {
|
||||
if (tracker.trackerDataType == TrackerDataType.FLEX_RESISTANCE) {
|
||||
tracker.trackerFlexHandler.resetMax()
|
||||
tracker.resetFilteringQuats(reference)
|
||||
return
|
||||
} else if (tracker.trackerDataType == TrackerDataType.FLEX_ANGLE) {
|
||||
return
|
||||
} else if (!resetMountingFeet && isFootTracker()) {
|
||||
} else if (!resetMountingFeet && tracker.trackerPosition.isFoot() && !forceFeet) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -423,25 +424,25 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
var yawAngle = atan2(rotVector.x, rotVector.z)
|
||||
|
||||
// Adjust for T-Pose and fingers
|
||||
if ((isLeftArmTracker() && armsResetMode == ArmsResetModes.TPOSE_DOWN) ||
|
||||
(isRightArmTracker() && armsResetMode == ArmsResetModes.TPOSE_UP) ||
|
||||
isLeftFingerTracker()
|
||||
if ((tracker.trackerPosition.isLeftArm() && armsResetMode == ArmsResetModes.TPOSE_DOWN) ||
|
||||
(tracker.trackerPosition.isRightArm() && armsResetMode == ArmsResetModes.TPOSE_UP) ||
|
||||
tracker.trackerPosition.isLeftFinger()
|
||||
) {
|
||||
// Tracker goes right
|
||||
yawAngle -= FastMath.HALF_PI
|
||||
}
|
||||
if ((isLeftArmTracker() && armsResetMode == ArmsResetModes.TPOSE_UP) ||
|
||||
(isRightArmTracker() && armsResetMode == ArmsResetModes.TPOSE_DOWN) ||
|
||||
isRightFingerTracker()
|
||||
if ((tracker.trackerPosition.isLeftArm() && armsResetMode == ArmsResetModes.TPOSE_UP) ||
|
||||
(tracker.trackerPosition.isRightArm() && armsResetMode == ArmsResetModes.TPOSE_DOWN) ||
|
||||
tracker.trackerPosition.isRightFinger()
|
||||
) {
|
||||
// Tracker goes left
|
||||
yawAngle += FastMath.HALF_PI
|
||||
}
|
||||
|
||||
// Adjust for forward/back arms and thighs
|
||||
val isLowerArmBack = armsResetMode == ArmsResetModes.BACK && (isLeftLowerArmTracker() || isRightLowerArmTracker())
|
||||
val isArmForward = armsResetMode == ArmsResetModes.FORWARD && (isLeftArmTracker() || isRightArmTracker())
|
||||
if (!isThighTracker() && !isArmForward && !isLowerArmBack) {
|
||||
val isLowerArmBack = armsResetMode == ArmsResetModes.BACK && (tracker.trackerPosition.isLeftLowerArm() || tracker.trackerPosition.isRightLowerArm())
|
||||
val isArmForward = armsResetMode == ArmsResetModes.FORWARD && (tracker.trackerPosition.isLeftArm() || tracker.trackerPosition.isRightArm())
|
||||
if (!tracker.trackerPosition.isThigh() && !isArmForward && !isLowerArmBack) {
|
||||
// Tracker goes back
|
||||
yawAngle -= FastMath.PI
|
||||
}
|
||||
@@ -595,98 +596,4 @@ class TrackerResetsHandler(val tracker: Tracker) {
|
||||
}
|
||||
return totalMatrix.toQuaternion()
|
||||
}
|
||||
|
||||
private fun isThighTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.LEFT_UPPER_LEG ||
|
||||
it == TrackerPosition.RIGHT_UPPER_LEG
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isLeftArmTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.LEFT_SHOULDER ||
|
||||
it == TrackerPosition.LEFT_UPPER_ARM ||
|
||||
it == TrackerPosition.LEFT_LOWER_ARM ||
|
||||
it == TrackerPosition.LEFT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isRightArmTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.RIGHT_SHOULDER ||
|
||||
it == TrackerPosition.RIGHT_UPPER_ARM ||
|
||||
it == TrackerPosition.RIGHT_LOWER_ARM ||
|
||||
it == TrackerPosition.RIGHT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isLeftLowerArmTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.LEFT_LOWER_ARM ||
|
||||
it == TrackerPosition.LEFT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isRightLowerArmTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.RIGHT_LOWER_ARM ||
|
||||
it == TrackerPosition.RIGHT_HAND
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isFootTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.LEFT_FOOT ||
|
||||
it == TrackerPosition.RIGHT_FOOT
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isLeftFingerTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.LEFT_THUMB_METACARPAL ||
|
||||
it == TrackerPosition.LEFT_THUMB_PROXIMAL ||
|
||||
it == TrackerPosition.LEFT_THUMB_DISTAL ||
|
||||
it == TrackerPosition.LEFT_INDEX_PROXIMAL ||
|
||||
it == TrackerPosition.LEFT_INDEX_INTERMEDIATE ||
|
||||
it == TrackerPosition.LEFT_INDEX_DISTAL ||
|
||||
it == TrackerPosition.LEFT_MIDDLE_PROXIMAL ||
|
||||
it == TrackerPosition.LEFT_MIDDLE_INTERMEDIATE ||
|
||||
it == TrackerPosition.LEFT_MIDDLE_DISTAL ||
|
||||
it == TrackerPosition.LEFT_RING_PROXIMAL ||
|
||||
it == TrackerPosition.LEFT_RING_INTERMEDIATE ||
|
||||
it == TrackerPosition.LEFT_RING_DISTAL ||
|
||||
it == TrackerPosition.LEFT_LITTLE_PROXIMAL ||
|
||||
it == TrackerPosition.LEFT_LITTLE_INTERMEDIATE ||
|
||||
it == TrackerPosition.LEFT_LITTLE_DISTAL
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isRightFingerTracker(): Boolean {
|
||||
tracker.trackerPosition?.let {
|
||||
return it == TrackerPosition.RIGHT_THUMB_METACARPAL ||
|
||||
it == TrackerPosition.RIGHT_THUMB_PROXIMAL ||
|
||||
it == TrackerPosition.RIGHT_THUMB_DISTAL ||
|
||||
it == TrackerPosition.RIGHT_INDEX_PROXIMAL ||
|
||||
it == TrackerPosition.RIGHT_INDEX_INTERMEDIATE ||
|
||||
it == TrackerPosition.RIGHT_INDEX_DISTAL ||
|
||||
it == TrackerPosition.RIGHT_MIDDLE_PROXIMAL ||
|
||||
it == TrackerPosition.RIGHT_MIDDLE_INTERMEDIATE ||
|
||||
it == TrackerPosition.RIGHT_MIDDLE_DISTAL ||
|
||||
it == TrackerPosition.RIGHT_RING_PROXIMAL ||
|
||||
it == TrackerPosition.RIGHT_RING_INTERMEDIATE ||
|
||||
it == TrackerPosition.RIGHT_RING_DISTAL ||
|
||||
it == TrackerPosition.RIGHT_LITTLE_PROXIMAL ||
|
||||
it == TrackerPosition.RIGHT_LITTLE_INTERMEDIATE ||
|
||||
it == TrackerPosition.RIGHT_LITTLE_DISTAL
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package dev.slimevr.tracking.trackers
|
||||
|
||||
import solarxr_protocol.datatypes.BodyPart
|
||||
|
||||
object TrackerUtils {
|
||||
|
||||
/**
|
||||
@@ -90,4 +92,14 @@ object TrackerUtils {
|
||||
fun getFirstAvailableTracker(
|
||||
vararg trackers: Tracker?,
|
||||
): Tracker? = trackers.firstOrNull { it != null }
|
||||
|
||||
val allBodyPartsButFingers = listOf(
|
||||
BodyPart.HEAD, BodyPart.NECK, BodyPart.UPPER_CHEST,
|
||||
BodyPart.CHEST, BodyPart.WAIST, BodyPart.HIP,
|
||||
BodyPart.LEFT_UPPER_LEG, BodyPart.RIGHT_UPPER_LEG, BodyPart.LEFT_LOWER_LEG,
|
||||
BodyPart.RIGHT_LOWER_LEG, BodyPart.LEFT_LOWER_ARM, BodyPart.RIGHT_LOWER_ARM,
|
||||
BodyPart.LEFT_UPPER_ARM, BodyPart.RIGHT_UPPER_ARM, BodyPart.LEFT_HAND,
|
||||
BodyPart.RIGHT_HAND, BodyPart.LEFT_SHOULDER, BodyPart.RIGHT_SHOULDER,
|
||||
BodyPart.LEFT_FOOT, BodyPart.RIGHT_FOOT,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ class TrackersHID(name: String, private val trackersConsumer: Consumer<Tracker>)
|
||||
mcu_id = dataReceived[i + 6].toUByte().toInt()
|
||||
// imu_id = dataReceived[i + 8].toUByte().toInt()
|
||||
// mag_id = dataReceived[i + 9].toUByte().toInt()
|
||||
// ushort big endian
|
||||
// ushort little endian
|
||||
fw_date = dataReceived[i + 11].toUByte().toInt() shl 8 or dataReceived[i + 10].toUByte().toInt()
|
||||
fw_major = dataReceived[i + 12].toUByte().toInt()
|
||||
fw_minor = dataReceived[i + 13].toUByte().toInt()
|
||||
@@ -319,11 +319,11 @@ class TrackersHID(name: String, private val trackersConsumer: Consumer<Tracker>)
|
||||
// Q15: 1 is represented as 0x7FFF, -1 as 0x8000
|
||||
// The sender can use integer saturation to avoid overflow
|
||||
for (j in 0..3) { // quat received as fixed Q15
|
||||
// Q15 as short big endian
|
||||
// Q15 as short little endian
|
||||
q[j] = dataReceived[i + 2 + j * 2 + 1].toInt() shl 8 or dataReceived[i + 2 + j * 2].toUByte().toInt()
|
||||
}
|
||||
for (j in 0..2) { // accel received as fixed 7, in m/s^2
|
||||
// Q7 as short big endian
|
||||
// Q7 as short little endian
|
||||
a[j] = dataReceived[i + 10 + j * 2 + 1].toInt() shl 8 or dataReceived[i + 10 + j * 2].toUByte().toInt()
|
||||
}
|
||||
}
|
||||
@@ -341,7 +341,7 @@ class TrackersHID(name: String, private val trackersConsumer: Consumer<Tracker>)
|
||||
q[1] = (q_buf shr 10 and 2047u).toInt()
|
||||
q[2] = (q_buf shr 21 and 2047u).toInt()
|
||||
for (j in 0..2) { // accel received as fixed 7, in m/s^2
|
||||
// Q7 as short big endian
|
||||
// Q7 as short little endian
|
||||
a[j] = dataReceived[i + 9 + j * 2 + 1].toInt() shl 8 or dataReceived[i + 9 + j * 2].toUByte().toInt()
|
||||
}
|
||||
rssi = dataReceived[i + 15].toUByte().toInt()
|
||||
@@ -355,11 +355,11 @@ class TrackersHID(name: String, private val trackersConsumer: Consumer<Tracker>)
|
||||
|
||||
4 -> { // full precision quat and mag, no extra data
|
||||
for (j in 0..3) { // quat received as fixed Q15
|
||||
// Q15 as short big endian
|
||||
// Q15 as short little endian
|
||||
q[j] = dataReceived[i + 2 + j * 2 + 1].toInt() shl 8 or dataReceived[i + 2 + j * 2].toUByte().toInt()
|
||||
}
|
||||
for (j in 0..2) { // mag received as fixed 10, in gauss
|
||||
// Q10 as short big endian
|
||||
// Q10 as short little endian
|
||||
m[j] = dataReceived[i + 10 + j * 2 + 1].toInt() shl 8 or dataReceived[i + 10 + j * 2].toUByte().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,3 +40,8 @@ project(":server").projectDir = File("server")
|
||||
include(":server:core")
|
||||
include(":server:desktop")
|
||||
include(":server:android")
|
||||
try {
|
||||
apply(from = "tauri.settings.gradle")
|
||||
} catch(e: Exception) {
|
||||
println("Couldn't enable tauri stuff")
|
||||
}
|
||||
|
||||
Submodule solarxr-protocol updated: 97f5896db4...df26226d10
Reference in New Issue
Block a user