Compare commits

...

119 Commits

Author SHA1 Message Date
Louka
472f6d8fc0 add accessories wip 2023-07-29 02:19:08 -04:00
Erimel
d89a4c2704 Send any computed tracker via VMC for props (#719)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-07-27 15:43:34 +03:00
Erimel
0ad237a219 Improve defaults SkeletonValues & add ratios in gui (#743) 2023-07-27 15:42:28 +03:00
Uriel
9c980f06f9 Make manual proportion list grow if there is space (#784)
Co-authored-by: lucas lelievre <loucass003@gmail.com>
2023-07-27 15:41:47 +03:00
Collin
f607693d83 Fix toe snap (#793) 2023-07-25 02:53:46 -04:00
Butterscotch!
27faa1908c Fix Autobone comment on the wrong line (#791) 2023-07-23 13:19:33 -04:00
Uriel
39cd1f9ba9 Autobone config migration is in wrong version (#792) 2023-07-22 03:49:27 -04:00
Erimel
c59f20a79a make sentences consistents (#789) 2023-07-20 16:30:58 -04:00
Erimel
e7de25dfab Clarify "extended" skeleton toggles in GUI (#779) 2023-07-20 15:39:24 -04:00
Erimel
74f1d8ed61 Drift compensation tracker and HMD requirement (#750) 2023-07-20 15:32:52 -04:00
Erimel
ad41c46092 Bundle & Receive OSCTrackers (#773) 2023-07-20 15:25:14 -04:00
Erimel
f3346bbeee Make displayName consistent via hash (#775) 2023-07-20 15:14:52 -04:00
Erimel
ca6f82492d Refresh headShift when setting trackers (#781) 2023-07-20 15:10:08 -04:00
Uriel
02acc6ede1 Improvements on the Autobone GUI (#776)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-07-20 11:19:43 +03:00
Uriel
d9c631fcf6 Fix CI release bundling (#777) 2023-07-20 11:15:55 +03:00
Uriel
ea9df2c31f Add accessibility settings (#774) 2023-07-20 11:14:51 +03:00
Collin
e18bd2d382 Better tap detection (#778) 2023-07-20 11:06:48 +03:00
Uriel
b6a681b1bb Save config and logs on appdata folder (#770) 2023-07-20 11:02:52 +03:00
Uriel
793dd374f8 Update appstream metadata (#762) 2023-07-20 11:00:52 +03:00
Uriel
97b617bb24 Add me to GUI codeowners (#782) 2023-07-20 10:59:47 +03:00
lucas lelievre
1aa32b8264 Fix Scroll on mobile (#785) 2023-07-20 10:59:23 +03:00
Uriel
5c2c6749c3 Move SteamVR code to desktop subproject (#755) 2023-07-19 16:32:00 -04:00
Uriel
e472b12e83 Add rust file logging (#752) 2023-07-19 16:11:48 -04:00
MarcoM
75fc1c37d3 fix: filter non imu in connected tracker (#763) 2023-07-17 17:54:16 -04:00
Erimel
9c4b9b401e Don't create new skeletons (#761) 2023-07-15 23:37:14 -04:00
Erimel
4243951214 Prioritize non-computed head tracker (#751)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-07-15 23:07:39 -04:00
Collin
2f61d5b4b8 Mocap mode (#749)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
Co-authored-by: Erimel <marioluigivideo@gmail.com>
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-07-14 22:45:18 +03:00
Uriel
35e6b8b721 Manual mounting overhaul (#745) 2023-07-14 22:30:26 +03:00
Eiren Rain
82db6a1ff5 Separate the server in subprojects (#727) 2023-07-14 20:22:49 +02:00
Uriel
17be65d2a2 Merge branch 'main' into subprojects 2023-07-10 15:21:02 -03:00
Erimel
db2f7fbd49 Don't log non-imu trackers' drift (#759) 2023-07-09 20:36:12 -04:00
Uriel
95f1bfd52f Merge branch 'main' into subprojects 2023-07-09 21:30:10 -03:00
Erimel
7511e0098e Fix chest tracker SteamVR battery (#772)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-07-09 20:17:46 -04:00
Uriel
f0f2731387 second fix 2023-07-07 21:47:16 -03:00
Uriel
5f3182e2c6 fix merge 2023-07-07 21:43:53 -03:00
Uriel
8b4a2843a1 Merge branch 'main' into subprojects 2023-07-07 19:54:50 -03:00
Collin Kees
d227b97843 Adjusted com calcs (#769) 2023-07-07 14:16:12 -04:00
Eiren Rain
7f11534fc1 Fix status not working (#765) 2023-07-04 21:26:25 +02:00
Uriel
af2cf10c16 thats weird... 2023-07-04 16:19:58 -03:00
Eiren Rain
055fd78d4d New Pontoon translations (#739) 2023-07-04 19:28:05 +02:00
phoebe
26b472893d Pontoon: Update Turkish (tr) localization of GUI
Co-authored-by: Stupid <dfgfdgrwEHRE@gmail.com>
Co-authored-by: phoebe <brnjyhvmn@gmail.com>
2023-07-04 17:24:55 +00:00
Kamilake
26fbbebb89 Pontoon: Update Korean (ko) localization of GUI
Co-authored-by: Kamilake <exjang0@gmail.com>
2023-07-04 17:24:55 +00:00
FennT
2eba83411c Pontoon: Update Arabic (ar) localization of GUI
Co-authored-by: FennT <0094falcon@gmail.com>
2023-07-04 17:24:55 +00:00
Vyolex
80ffa1a9b4 Pontoon: Update Dutch (nl) localization of GUI
Co-authored-by: Vyolex <25586367+Vyolex@users.noreply.github.com>
2023-07-04 17:24:55 +00:00
Uriel
1b06799315 fix extra space on Norwegian 2023-07-04 17:24:55 +00:00
Erimel
046b0b8be3 Pontoon: Update French (fr) localization of GUI
Co-authored-by: Erimel <loukalemire@gmail.com>
2023-07-04 17:24:55 +00:00
Meow Wei
f4b16f2cdb Pontoon: Update Traditional Chinese (zh-Hant) localization of GUI
Co-authored-by: Meow Wei <medicalwei@gmail.com>
2023-07-04 17:24:55 +00:00
HappyTownCats
b266afedea Pontoon: Update Ukrainian (uk) localization of GUI
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: HappyTownCats <HappyTownCats@gmail.com>
Co-authored-by: nyarl <nyarl@outlook.com>
2023-07-04 17:24:55 +00:00
Kaiera huzu
646eb94f72 Pontoon: Update Thai (th) localization of GUI
Co-authored-by: Kaiera huzu <patsakorn9090@gmail.com>
2023-07-04 17:24:55 +00:00
Hornil
1bf79fc72d Pontoon: Update Russian (ru) localization of GUI
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: SummerArtz <summerpzmail@gmail.com>
Co-authored-by: Hornil <vixlyaev@gmail.com>
2023-07-04 17:24:55 +00:00
ReDoX
cddbb93c99 Pontoon: Update Polish (pl) localization of GUI
Co-authored-by: ReDoX <redox01@o2.pl>
2023-07-04 17:24:55 +00:00
beq
5463eee217 Pontoon: Update Japanese (ja) localization of GUI
Co-authored-by: 白貓 <yen.max@gmail.com>
Co-authored-by: beq <beqbdean@gmail.com>
Co-authored-by: 空影/Sorakage <sorakage033@gmail.com>
2023-07-04 17:24:55 +00:00
namakeingo
c93709f80f Pontoon: Update Hebrew (he) localization of GUI
Co-authored-by: namakeingo <namakeingo@gmail.com>
2023-07-04 17:24:55 +00:00
namakeingo
f6b915a88e Pontoon: Update Greek (el) localization of GUI
Co-authored-by: namakeingo <namakeingo@gmail.com>
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: odydoubouridis <odydoubouridis@gmail.com>
2023-07-04 17:24:55 +00:00
thearxari
9231356638 Pontoon: Update Czech (cs) localization of GUI
Co-authored-by: thearxari <thearxari@gmail.com>
2023-07-04 17:24:55 +00:00
TheDevMinerTV
7bb32a382a Pontoon: Update German (de) localization of GUI
Co-authored-by: TheDevMinerTV <devminer@devminer.xyz>
Co-authored-by: unlogisch <unlogisch@gmx.ch>
Co-authored-by: Zahnatom <zahnatomletsplay@gmail.com>
2023-07-04 17:24:55 +00:00
Disappear9
a17f651f64 Pontoon: Update Simplified Chinese (zh-Hans) localization of GUI
Co-authored-by: Disappear9 <disappear9@outlook.com>
2023-07-04 17:24:55 +00:00
Gaabbu
c9f0f6e27c Pontoon: Update Portuguese (pt-BR) localization of GUI
Co-authored-by: Gaabbu <gabrielsonada@outlook.com.br>
2023-07-04 17:24:55 +00:00
Erimel
3defd47c29 Improve Autobone upperChest and fix VMC upperChest (#754) 2023-07-04 20:24:50 +03:00
Erimel
3068fada17 Don't ask twice to reset non-imu trackers (#760)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-07-04 20:24:16 +03:00
Uriel
efd20ee7b2 Merge branch 'main' into subprojects 2023-07-03 23:10:19 -03:00
Collin Kees
e71ed5cf6c Acceleration alignment fix (#737)
Co-authored-by: Erimel <marioluigivideo@gmail.com>
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-07-03 19:43:28 -04:00
ImUrX
c076ebabb3 Merge branch 'main' into subprojects 2023-07-02 17:06:53 -03:00
Erimel
0ccd7e260c Add upper chest tracking point (#716) 2023-07-02 14:33:36 +03:00
Uriel
9e650dad08 Merge branch 'main' into subprojects 2023-07-01 23:05:57 -07:00
lucas lelievre
36c4889d75 mobile body proportions (#718)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-07-01 20:29:31 -04:00
Uriel
8da9e63c45 Fix Dropdown not opening (#744) 2023-07-01 19:59:21 -04:00
Uriel
dc22b503e8 Merge branch 'main' into subprojects 2023-06-29 19:04:07 -03:00
Butterscotch!
5e81e3ac4c Make AutoBone more modular and readable (#684) 2023-06-30 00:44:14 +03:00
Uriel
0bd6a9002a Merge branch 'main' into subprojects 2023-06-26 20:26:28 -03:00
Uriel
9c7558cae8 it works then 2023-06-26 23:07:10 +00:00
Uriel
dabb78e545 Fix mobile bugs (#740)
Co-authored-by: lucas lelievre <loucass003@gmail.com>
2023-06-27 00:49:16 +03:00
Evgeniy Zhabotinskiy
582618ee72 Stop unconditionally hogging serial ports (#692) 2023-06-27 00:47:15 +03:00
ImUrX
d89a53ef44 Merge branch 'main' into subprojects 2023-06-26 17:51:22 -03:00
ImUrX
525f29f3c5 add copy script 2023-06-26 17:50:11 -03:00
Erimel
047667432c That's cringe (#742) 2023-06-26 23:10:23 +03:00
Erimel
f4261d5bc2 Clear untranslated keys (#741) 2023-06-24 23:20:40 -04:00
Butterscotch!
c94d71c24f Disable gradle config cache 2023-06-24 21:50:37 -04:00
Butterscotch!
31ff3f4868 Re-revert broken dependency update 2023-06-24 21:25:14 -04:00
Butterscotch!
a6911e072c Fix workflow targeting wrong build directory 2023-06-24 20:43:26 -04:00
Butterscotch!
bf062c9b65 Merge remote-tracking branch 'upstream/main' into pr/727 2023-06-24 20:12:21 -04:00
ImUrX
8945e05354 just delete it then lol 2023-06-16 16:15:12 -03:00
ImUrX
ea3cdb7658 pls work? 2023-06-16 16:07:45 -03:00
ImUrX
ae40121a31 pls work 2023-06-16 15:01:17 -03:00
ImUrX
f64a45fb2e fix unresolved reference from merge 2023-06-16 14:50:25 -03:00
ImUrX
cb19aa17cc forgot server folder 2023-06-16 14:48:56 -03:00
ImUrX
4564671b38 Merge branch 'main' into subprojects 2023-06-16 14:45:26 -03:00
ImUrX
60f74d6d5c fix tests 2023-06-16 14:44:14 -03:00
ImUrX
4450260dd0 make softlink valid 2023-06-15 18:02:19 -03:00
ImUrX
55f030a145 spotless 2023-06-15 17:52:09 -03:00
ImUrX
3038de8a5f Merge branch 'main' into subprojects 2023-06-15 17:39:25 -03:00
ImUrX
338e153834 keep fixing gradle script 2023-06-15 16:33:07 -03:00
ImUrX
544efb6efe fetch tags in gh actions 2023-06-15 15:59:43 -03:00
ImUrX
0e64f1241f Merge branch 'main' into subprojects 2023-06-15 15:38:23 -03:00
ImUrX
ffe530dc94 move bridges to desktop 2023-06-15 15:37:21 -03:00
ImUrX
a8ce510f70 fix soft link 2023-06-15 01:16:32 -03:00
ImUrX
1b17fcbec3 android 2023-06-15 01:16:32 -03:00
ImUrX
01f1d2ee56 im having so much fun 2023-06-15 01:16:31 -03:00
ImUrX
d14a7bb5e7 it runs 2023-06-15 01:16:30 -03:00
ImUrX
a14a2ea253 im ruining everything 2023-06-15 01:16:27 -03:00
Butterscotch!
b67de108e7 Bump versions 2023-06-13 20:30:44 -04:00
Butterscotch!
e4a4f38c15 Disable cache on WebView 2023-06-13 20:30:44 -04:00
Butterscotch!
858354eee8 Revert broken dependency update 2023-06-13 20:30:44 -04:00
Butterscotch!
fcb736d371 Fix gradle build somewhat 2023-06-13 20:30:44 -04:00
Butterscotch!
f6d8026761 Don't cache & try more to allow zooming on GUI 2023-06-13 20:30:44 -04:00
Butterscotch!
cb5e27875c Update Gradle stuff & fix compilation + proguard 2023-06-13 20:30:44 -04:00
Butterscotch!
72f506822a Update Gradle stuff 2023-06-13 20:30:43 -04:00
Butterscotch!
4e942fded5 Revert "Work around TransformNode race condition"
This reverts commit 23a2abbbdcc9a070c6fe907ec56bc2d10a607b27.
2023-06-13 20:30:43 -04:00
Butterscotch!
463e558e7f Enable WebView debugging 2023-06-13 20:30:43 -04:00
Butterscotch!
a1db52144a Work around TransformNode race condition 2023-06-13 20:30:43 -04:00
Butterscotch!
81b7ea0967 Fix screen rotation crashing 2023-06-13 20:30:43 -04:00
Butterscotch!
a489e32828 Fix Gradle build 2023-06-13 20:30:43 -04:00
Butterscotch!
6eaf04ba64 Update version code 2023-06-13 20:30:42 -04:00
Butterscotch!
b8ceaa6bc0 Fix OSC Android fuckery 2023-06-13 20:30:42 -04:00
Butterscotch!
6b7c47d36c Add GUI webview & remove titlebar 2023-06-13 20:30:42 -04:00
Butterscotch!
c0f8fb1758 Add locally hosted web GUI 2023-06-13 20:30:42 -04:00
Butterscotch!
07600f0133 Set version number and add icons 2023-06-13 20:30:42 -04:00
Butterscotch!
3634bedef1 Reduce minimum SDK version to 26 2023-06-13 20:30:42 -04:00
Butterscotch!
e864487246 Add basic support for Android
- Add Android build scripts
- Add Android GUI and `MainActivity`
- Fix Java records
- Fix `Path.of` errors
- Update Main and MainActivity to match better
2023-06-13 20:30:42 -04:00
381 changed files with 10480 additions and 5848 deletions

6
.github/CODEOWNERS vendored
View File

@@ -1,9 +1,9 @@
# Global code owner
* @Eirenliel
# Make Loucas the owner of all GUI stuff
/gui/ @loucass003
/package-lock.json @loucass003
# Make Loucas and Uriel the owners of all GUI stuff
/gui/ @loucass003 @ImUrX
/package-lock.json @loucass003 @ImUrX
# Uriel and Erimel responsible for i18n
/gui/public/i18n/ @ImUrX @Louka3000

View File

@@ -22,6 +22,8 @@ jobs:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Get tags
run: git fetch --tags origin --recurse-submodules=no
- name: Set up JDK 17
uses: actions/setup-java@v3
@@ -32,6 +34,9 @@ jobs:
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- run: mkdir ./gui/dist && touch ./gui/dist/somefile
shell: bash
- name: Check code formatting
run: ./gradlew spotlessCheck
@@ -46,6 +51,8 @@ jobs:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Get tags
run: git fetch --tags origin --recurse-submodules=no
- name: Set up JDK 17
uses: actions/setup-java@v3
@@ -65,7 +72,7 @@ jobs:
# Artifact name
name: "SlimeVR-Server" # optional, default is artifact
# A file, directory or wildcard pattern that describes what to upload
path: server/build/libs/*
path: server/desktop/build/libs/*
- name: Upload to draft release
uses: softprops/action-gh-release@v1
@@ -74,7 +81,7 @@ jobs:
draft: true
generate_release_notes: true
files: |
server/build/libs/*
server/desktop/build/libs/*
bundle-linux:
@@ -89,7 +96,7 @@ jobs:
- uses: actions/download-artifact@v3
with:
name: "SlimeVR-Server"
path: server/build/libs/
path: server/desktop/build/libs/
- name: Set up Linux dependencies
uses: awalsh128/cache-apt-pkgs-action@latest
@@ -134,7 +141,7 @@ jobs:
cd target/release/bundle/appimage
chmod a+x slimevr*.AppImage
./slimevr*.AppImage --appimage-extract
cp $( git rev-parse --show-toplevel )/server/build/libs/slimevr.jar squashfs-root/slimevr.jar
cp $( git rev-parse --show-toplevel )/server/desktop/build/libs/slimevr.jar squashfs-root/slimevr.jar
chmod 644 squashfs-root/slimevr.jar
appimagetool squashfs-root slimevr*.AppImage
@@ -172,7 +179,7 @@ jobs:
- uses: actions/download-artifact@v3
with:
name: "SlimeVR-Server"
path: server/build/libs/
path: server/desktop/build/libs/
- name: Cache cargo dependencies
uses: Swatinem/rust-cache@v2
@@ -193,7 +200,7 @@ jobs:
- name: Modify Application
run: |
cd target/release/bundle/macos/slimevr.app/Contents/MacOS
cp $( git rev-parse --show-toplevel )/server/build/libs/slimevr.jar ./
cp $( git rev-parse --show-toplevel )/server/desktop/build/libs/slimevr.jar ./
cd ../../../../dmg/
./bundle_dmg.sh --volname slimevr --icon slimevr 180 170 --app-drop-link 480 170 \
--window-size 660 400 --hide-extension ../macos/slimevr.app \
@@ -237,7 +244,7 @@ jobs:
- uses: actions/download-artifact@v3
with:
name: "SlimeVR-Server"
path: server/build/libs/
path: server/desktop/build/libs/
- name: Cache cargo dependencies
uses: Swatinem/rust-cache@v2
@@ -260,8 +267,8 @@ jobs:
run: |
mkdir SlimeVR
cp gui/src-tauri/icons/icon.ico ./SlimeVR/run.ico
cp server/build/libs/slimevr.jar ./SlimeVR/slimevr.jar
cp server/resources/* ./SlimeVR/
cp server/desktop/build/libs/slimevr.jar ./SlimeVR/slimevr.jar
cp server/core/resources/* ./SlimeVR/
cp target/release/slimevr.exe ./SlimeVR/
7z a -tzip SlimeVR-win64.zip ./SlimeVR/

3
.gitignore vendored
View File

@@ -36,3 +36,6 @@ build/
# direnv has been claimed for Nix usage
.direnv/
# Ignore Android local properties
local.properties

413
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,3 +11,7 @@ edition = "2021"
license = "MIT OR Apache-2.0"
rust-version = "1.65" # This version stabilized GATs and let-else
repository = "https://github.com/SlimeVR/SlimeVR-Server"
[profile.release]
lto = "thin"
strip = "debuginfo" # Only affects Unix binaries with DWARF

View File

@@ -1,26 +1,3 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.20.2")
}
}
plugins {
kotlin("jvm") version "1.8.21"
}
subprojects {
plugins.apply("kotlinx-atomicfu")
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
}
repositories {
mavenCentral()
}
kotlin {
jvmToolchain(17)
id("org.ajoberstar.grgit") version "5.2.0"
}

View File

@@ -30,7 +30,7 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
<url type="contribute">https://github.com/SlimeVR/SlimeVR-Server/blob/main/CONTRIBUTING.md</url>
<url type="contact">https://discord.gg/SlimeVR</url>
<recommends>
<display_length compare="ge">880</display_length>
<display_length compare="ge">300</display_length>
</recommends>
<supports>
<control>pointing</control>
@@ -44,8 +44,7 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
<description>
<p>
<code>SlimeVR</code>
is a set of open hardware sensors and open source software that facilitates full-body
SlimeVR is a set of open hardware sensors and open source software that facilitates full-body
tracking (FBT) in virtual reality. With no base station required, SlimeVR makes wireless
VR FBT affordable and comfortable.
</p>
@@ -60,6 +59,17 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
</screenshot>
</screenshots>
<releases>
<release version="0.8.3" date="2023-07-09"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.3</url></release>
<release version="0.8.2" date="2023-07-09"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.2</url></release>
<release version="0.8.2-rc.1" type="development" date="2023-07-07"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.2-rc.1</url></release>
<release version="0.8.1" date="2023-07-04"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.1</url></release>
<release version="0.8.0" date="2023-06-22"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.0</url></release>
<release version="0.8.0-rc.3" type="development" date="2023-06-20"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.0-rc.3</url></release>
<release version="0.8.0-rc.2" type="development" date="2023-06-15"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.0-rc.2</url></release>
<release version="0.8.0-rc.1" type="development" date="2023-06-01"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.0-rc.1</url></release>
<release version="0.7.1" date="2023-04-14"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.7.1</url></release>
<release version="0.7.0" date="2023-04-11"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.7.0</url></release>
<release version="0.6.3" date="2023-02-22"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.3</url></release>
<release version="0.6.2" date="2023-02-17"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.2</url></release>
<release version="0.6.1" date="2023-02-12"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.1</url></release>
<release version="0.6.0" date="2023-01-05"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.6.0</url></release>

View File

@@ -8,3 +8,12 @@ org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAME
kotlin.code.style=official
# https://github.com/Kotlin/kotlinx-atomicfu#atomicfu-compiler-plugin
kotlinx.atomicfu.enableJvmIrTransformation=true
android.useAndroidX=true
android.nonTransitiveRClass=true
org.gradle.unsafe.configuration-cache=false
kotlinVersion=1.9.0-RC
spotlessVersion=6.12.0
shadowJarVersion=8.1.1
buildconfigVersion=3.1.0

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

7
gradlew vendored
View File

@@ -85,6 +85,9 @@ done
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -194,10 +197,6 @@ if "$cygwin" || "$msys" ; then
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in

5
gui/.gitignore vendored
View File

@@ -25,5 +25,6 @@ yarn-error.log*
*.log
/dist
# vite
/dist
/stats.html

View File

@@ -29,10 +29,11 @@
"react-modal": "3.15.1",
"react-responsive": "^9.0.2",
"react-router-dom": "^6.2.2",
"semver": "^7.5.0",
"semver": "^7.5.3",
"solarxr-protocol": "file:../solarxr-protocol",
"three": "^0.148.0",
"typescript": "^4.6.3"
"ts-pattern": "^5.0.1",
"typescript": "^5.1.6"
},
"scripts": {
"start": "vite --force",
@@ -64,29 +65,30 @@
]
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.0",
"@tailwindcss/forms": "^0.5.3",
"@tauri-apps/cli": "^1.4.0",
"@types/file-saver": "^2.0.5",
"@types/react": "18.0.25",
"@types/react-dom": "^18.0.5",
"@types/react-modal": "3.13.1",
"@types/three": "^0.148.0",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.0",
"@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1",
"autoprefixer": "^10.4.4",
"cross-env": "^7.0.3",
"eslint": "^8.18.0",
"eslint": "^8.44.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-import-resolver-typescript": "^3.1.1",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.0",
"eslint-plugin-react": "^7.30.1",
"eslint-import-resolver-typescript": "^3.5.5",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"postcss": "^8.4.12",
"prettier": "^2.7.1",
"postcss": "^8.4.24",
"prettier": "^2.8.8",
"pretty-quick": "^3.1.3",
"rollup-plugin-visualizer": "^5.9.2",
"tailwind-gradient-mask-image": "^1.0.0",
"tailwindcss": "^3.3.1",
"vite": "^4.0.3"
"tailwindcss": "^3.3.2",
"vite": "^4.3.9"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -12,12 +12,17 @@ websocket-connection_lost = انقطع الاتصال بالسيرفر. يتم
## Update notification
version_update-title = نسخة جديدة متوفرة: { $version }
version_update-description = سيؤدي النقر على "{ version_update-update }" إلى تنزيل مثبت SlimeVR نيابة عنك.
version_update-update = تحديث
version_update-close = أغلق
## Tips
tips-find_tracker = لست متأكد من أجهزة التعقب؟ قم بتحريك الجهاز لتحديد العنصر المناسب.
tips-do_not_move_heels = يرجى عدم تحريك كاحليك أثناء التسجيل!
tips-file_select = اسحب الملفات وأفلتها لاستخدامها أو <u> تصفح </ u>
tips-tap_setup = يمكنك النقر ببطء مرتين على جهاز التعقب لاختياره بدلاً من تحديده من القائمة.
## Body parts
@@ -31,6 +36,7 @@ body_part-RIGHT_HAND = اليد اليمنى
body_part-RIGHT_UPPER_LEG = الفخذ الأيمن
body_part-RIGHT_LOWER_LEG = الكاحل الأيمن
body_part-RIGHT_FOOT = القدم اليمنى
body_part-UPPER_CHEST = أعلى الصدر
body_part-CHEST = الصدر
body_part-WAIST = الخصر
body_part-HIP = الورك
@@ -48,8 +54,9 @@ skeleton_bone-NONE = غير محدد
skeleton_bone-HEAD = إمالة الرأس
skeleton_bone-NECK = طول العنق
skeleton_bone-torso_group = طول الجذع
skeleton_bone-CHEST = طول الصدر
skeleton_bone-UPPER_CHEST = طول أعلى الصدر
skeleton_bone-CHEST_OFFSET = درجة تشريد الصدر
skeleton_bone-CHEST = طول الصدر
skeleton_bone-WAIST = طول الخصر
skeleton_bone-HIP = طول الورك
skeleton_bone-HIP_OFFSET = درجة تشريد الورك
@@ -102,6 +109,8 @@ bvh-recording = تسجيل...
## Tracking pause
tracking-unpaused = إيقاف التعقب مؤقتا
tracking-paused = إلغاء الإيقاف التعقب
## Widget: Overlay settings
@@ -168,6 +177,9 @@ tracker-infos-custom_name = اسم مخصص
tracker-infos-url = عنوان URL لجهاز التعقب
tracker-infos-version = إصدار البرنامج الثابت
tracker-infos-hardware_rev = مراجعة الأجهزة
tracker-infos-hardware_identifier = معرف الجهاز
tracker-infos-imu = مستشعر IMU
tracker-infos-board_type = اللوحة الرئيسية
## Tracker settings
@@ -220,6 +232,7 @@ tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } الفخذ
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } الكاحل الأيمن؟
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } القدم اليمنى؟
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } وحدة التحكم اليمنى؟
tracker_selection_menu-UPPER_CHEST = { -tracker_selection-part } أعلى الصدر؟
tracker_selection_menu-CHEST = { -tracker_selection-part } الصدر؟
tracker_selection_menu-WAIST = { -tracker_selection-part } الخصر؟
tracker_selection_menu-HIP = { -tracker_selection-part } الورك؟
@@ -521,7 +534,26 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = العودة إلى معايرة التركيب
onboarding-reset_tutorial = إعادة البرنامج التعليمي
onboarding-reset_tutorial-description = هذه الميزة لم تنته بعد، فقط اضغط على متابعة
onboarding-reset_tutorial-explanation = أثناء استخدام أجهزة التعقب، قد تخرج عن المحاذاة بسبب انحراف IMU ، أو لأنك ربما تكون قد نقلتها جسديا. لديك عدة طرق لإصلاح هذا.
onboarding-reset_tutorial-skip = تخطى الخطوة
# Cares about multiline
onboarding-reset_tutorial-0 =
اضغط على جهاز التعقب المحدد { $taps } مرات لتشغيل إعادة ضبط الانعراج.
سيؤدي ذلك إلى جعل أجهزة التعقب تواجه نفس اتجاه HMD الخاص بك.
# Cares about multiline
onboarding-reset_tutorial-1 =
اضغط على جهاز التعقب المحدد { $taps } مرات لتشغيل إعادة تعيين كاملة.
يجب أن تكون واقفًا (i-pose). هناك تأخير لمدة 3 ثوان (قابل للتكوين) قبل إعادة التعيين بالكامل.
هذا يعيد تعيين موضع ودوران جميع جهاز التعقب. يجب أن يحل معظم المشاكل.
# Cares about multiline
onboarding-reset_tutorial-2 =
اضغط على المتتبع المحدد { $taps } مرات لتشغيل إعادة تعيين متصاعد.
يساعد إعادة التعيين المتصاعد في تحديد كيفية وضع أجهزة التعقب عليك بالفعل. لذلك إذا قمت بنقلهم عن طريق الخطأ وغيرت كيفية توجيههم بمقدار كبير ، فسيساعد ذلك.
يجب أن تكون في وضع تزلج كما هو موضح في معالج "التثبيت التلقائي" ولديك تأخير لمدة 3 ثوانٍ (قابل للتكوين) قبل أن يتم تشغيله.
## Setup start
@@ -576,9 +608,24 @@ onboarding-connect_tracker-next = لقد قمت بتوصيل جميع أجهزة
## Tracker calibration tutorial
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 = جاري المعايرة
onboarding-calibration_tutorial-status-success = رائع!
onboarding-calibration_tutorial-status-error = تم نقل جهاز التعقب
## Tracker assignment tutorial
onboarding-assignment_tutorial = كيفية تحضير جهاز تعقب Slime قبل وضعه
onboarding-assignment_tutorial-first_step = 1. ضع ملصق جزء الجسم (إذا كان لديك واحد) على جهاز التعقب وفقا لاختيارك
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = ملصق
onboarding-assignment_tutorial-second_step = 2. قم بتوصيل الشريط بجهاز التعقب الخاص بك ، مع الحفاظ على جانب الخطاف والحلقة من وجه الشريط في الاتجاه التالي:
onboarding-assignment_tutorial-second_step-continuation = يجب أن يكون جانب الخطاف والحلقة للامتداد في هذا الاتجاه:
onboarding-assignment_tutorial-done = وضعت الملصقات والأشرطة!
## Tracker assignment setup
@@ -589,10 +636,12 @@ onboarding-assign_trackers-description = دعنا نختار موقع أجهزة
# $assigned (Number) - Trackers that have been assigned a body part
# $trackers (Number) - Trackers connected to the server
onboarding-assign_trackers-assigned =
{ $assigned ->
{ $trackers ->
[zero] { $assigned } من { $trackers } أجهزة تعقب عينت
[one] جهاز واحد من { $trackers } أجهزة تعقب عينت
[two] جهازان من { $trackers } أجهزة تعقب عينت
[few] { $assigned } من { $trackers } أجهزة تعقب عينت
[many] { $assigned } من { $trackers } أجهزة تعقب عينت
*[other] { $assigned } من { $trackers } أجهزة تعقب عينت
}
onboarding-assign_trackers-advanced = إظهار مواقع التعيين المتقدمة
@@ -669,13 +718,15 @@ onboarding-assign_trackers-warning-WAIST =
## Tracker mounting method choose
onboarding-choose_mounting = ما طريقة معايرة التركيب المستخدمة؟
# Multiline text
onboarding-choose_mounting-description = اتجاه التركيب يصحح وضع أجهزة التعقب على جسمك.
onboarding-choose_mounting-auto_mounting = التركيب التلقائي
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = الموصى به
onboarding-choose_mounting-auto_mounting-label = تجريبي
onboarding-choose_mounting-auto_mounting-description = سيكتشف هذا تلقائيًا اتجاهات التركيب لجميع أجهزة التعقب من وضعين
onboarding-choose_mounting-manual_mounting = التركيب اليدوي
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = إذا كنت تعلم ماذا تفعل
onboarding-choose_mounting-manual_mounting-label = المستحسن
onboarding-choose_mounting-manual_mounting-description = سيسمح لك باختيار اتجاه التثبيت يدويًا لكل جهاز تعقب
## Tracker manual mounting setup
@@ -710,6 +761,10 @@ onboarding-automatic_mounting-put_trackers_on-next = ارتديت جميع أج
## Tracker proportions method choose
onboarding-choose_proportions = ما هي طريقة معايرة النسب التي يجب استخدامها؟
# Multiline string
onboarding-choose_proportions-description =
تستخدم نسب الجسم لمعرفة قياسات جسمك. هم مطلوبون لحساب مواقع أجهزة التعقب.
عندما لا تتطابق نسب جسمك مع تلك المحفوظة ، ستكون دقة التتبع لديك أسوأ وستلاحظ أشياء مثل التزلج أو الانزلاق ، أو أن جسمك لا يتطابق مع الصورة الرمزية بشكل جيد.
onboarding-choose_proportions-auto_proportions = النسب التلقائية
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = الموصى به
@@ -718,6 +773,8 @@ onboarding-choose_proportions-manual_proportions = النسب اليدوية
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = للمسات الصغيرة
onboarding-choose_proportions-manual_proportions-description = سيسمح لك بتعديل النسب يدويًا عن طريق تعديلها مباشرة
onboarding-choose_proportions-export = تصدير النسب
onboarding-choose_proportions-file_type = ملف نسب الجسم
## Tracker manual proportions setup
@@ -787,3 +844,10 @@ home-no_trackers = لم يتم الكشف أو تعيين عن أي جهاز ت
## Status system
status_system-StatusTrackerReset = يوصى بإجراء إعادة تعيين كاملة نظرًا لعدم تعديل واحد أو أكثر من أجهزة التعقب.
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] حاليًا غير متصل بتطبيق SlimeVR Feeder.
*[other] حاليًا غير متصل بـ SteamVR عبر برنامج تشغيل SlimeVR.
}
status_system-StatusTrackerError = يحتوي جهاز التعقب { $trackerName } على خطأ.

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,6 +10,9 @@
websocket-connecting = Připojování k serveru
websocket-connection_lost = Ztráta spojení se serverem. Pokus o obnovení připojení...
## Update notification
## Tips
tips-find_tracker = Nejste si jisti, který tracker je který? Zatřeste tracker a zvýrazní se odpovídající položka.
@@ -30,7 +30,6 @@ body_part-RIGHT_HAND = Pravá ruka
body_part-RIGHT_UPPER_LEG = Pravé stehno
body_part-RIGHT_LOWER_LEG = Pravý kotník
body_part-RIGHT_FOOT = Pravá noha
body_part-RIGHT_CONTROLLER = Pravý ovladač
body_part-CHEST = Hrudník
body_part-WAIST = Pás
body_part-HIP = Kyčel
@@ -41,7 +40,6 @@ body_part-LEFT_HAND = Levá ruka
body_part-LEFT_UPPER_LEG = Levé stehno
body_part-LEFT_LOWER_LEG = Levý kotník
body_part-LEFT_FOOT = Levá noha
body_part-LEFT_CONTROLLER = Levý ovladač
## Proportions
@@ -63,8 +61,6 @@ skeleton_bone-SHOULDERS_DISTANCE = Vzdálenost ramen
skeleton_bone-SHOULDERS_WIDTH = Šířka ramen
skeleton_bone-UPPER_ARM = Délka nadloktí
skeleton_bone-LOWER_ARM = Délka podloktí
skeleton_bone-CONTROLLER_Y = Vzdálenost ovladače Y
skeleton_bone-CONTROLLER_Z = Vzdálenost ovladače Z
skeleton_bone-ELBOW_OFFSET = Odsazení loktů
## Tracker reset buttons
@@ -72,7 +68,6 @@ skeleton_bone-ELBOW_OFFSET = Odsazení loktů
reset-reset_all = Obnovení všech proporcí
reset-full = Resetovat
reset-mounting = Obnovit montáž
reset-quick = Rychlý reset
## Serial detection stuff
@@ -93,11 +88,16 @@ navbar-mounting = Montážní kalibrace
navbar-onboarding = Průvodce nastavením
navbar-settings = Nastavení
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Nahrávat BVH
bvh-recording = Nahrávání...
## Tracking pause
tracking-unpaused = Pozastavit sledování
tracking-paused = Pokračovat se sledováním
## Widget: Overlay settings
widget-overlay = Překrytí
@@ -124,6 +124,7 @@ widget-developer_mode-more_info = Více informací
widget-imu_visualizer = Rotace
widget-imu_visualizer-rotation_raw = Nezpracované
widget-imu_visualizer-rotation_preview = Náhled
widget-imu_visualizer-rotation_hide = Skrýt
## Tracker status
@@ -160,6 +161,9 @@ tracker-infos-manufacturer = Výrobce
tracker-infos-display_name = Zobrazovaný název
tracker-infos-custom_name = Vlastní název
tracker-infos-url = URL Trackeru
tracker-infos-version = Verze firmwaru
tracker-infos-hardware_rev = Revize hardwaru
tracker-infos-board_type = Základní deska
## Tracker settings
@@ -297,8 +301,6 @@ settings-general-tracker_mechanics-drift_compensation-max_resets-label = Použí
## FK/Tracking settings
settings-general-fk_settings = Nastavení trackování
settings-general-fk_settings-leg_tweak = Vyladění nohou
settings-general-fk_settings-leg_tweak-description = Podlahovej-clip může snížit nebo dokonce eliminovat klipování s podlahou, ale může způsobit problémy, když klečíte na kolenou. Korekce-bruslení opravuje bruslení na ledě, avšak může snížit přesnost některých pohybových vzorců.
# Floor clip:
# why the name - came from the idea of noclip in video games, but is the opposite where clipping to the floor is a desired feature
# definition - Prevents the foot trackers from going lower than they where when a reset was performed
@@ -334,12 +336,6 @@ settings-general-gesture_control-taps =
[few] { $amount } klepnutí
*[other] { $amount } klepnutí
}
settings-general-gesture_control-quickResetEnabled = Povolit klepnutí pro rychlý resetování
settings-general-gesture_control-quickResetDelay = Zpoždění rychlého resetu
settings-general-gesture_control-quickResetTaps = Klepnutí pro rychlý reset
settings-general-gesture_control-resetEnabled = Povolit klepnutí pro resetování
settings-general-gesture_control-resetDelay = Zpoždění resetování
settings-general-gesture_control-resetTaps = Klepnutí pro resetování
settings-general-gesture_control-mountingResetEnabled = Povolit klepnutí pro resetování montáže
settings-general-gesture_control-mountingResetDelay = Zpoždění resetování montáže
settings-general-gesture_control-mountingResetTaps = Klepnutí pro resetování montáže
@@ -427,11 +423,14 @@ settings-osc-vrchat-network-address-placeholder = VRChat ip adresa
settings-osc-vrchat-network-trackers = Trackery
settings-osc-vrchat-network-trackers-description = Vypnuti a zapnutí odesílání konkrétních trackerů přes OSC.
settings-osc-vrchat-network-trackers-chest = Hrudník
settings-osc-vrchat-network-trackers-waist = Pás
settings-osc-vrchat-network-trackers-hip = Kyčel
settings-osc-vrchat-network-trackers-knees = Kolena
settings-osc-vrchat-network-trackers-feet = Chodidla
settings-osc-vrchat-network-trackers-elbows = Lokty
## VMC OSC settings
## Setup/onboarding menu
onboarding-skip = Přeskočit nastavení
@@ -459,15 +458,10 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Zpět na kalibraci montáže
onboarding-reset_tutorial = Obnovit tutoriál
onboarding-reset_tutorial-description = Tato funkce není dokončena, stačí stisknout tlačítko pokračovat
## Setup start
onboarding-home = Vítejte k SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
Přinášíme full-body tracking
pro každého
onboarding-home-start = Pusťme se do toho!
## Enter VR part of setup
@@ -492,10 +486,7 @@ onboarding-connect_tracker-description-p1 = Všechny zatím nepřipojené jednod
onboarding-connect_tracker-issue-serial = Mám potíže s připojením!
onboarding-connect_tracker-usb = USB Tracker
onboarding-connect_tracker-connection_status-connecting = Odesílání přihlašovacích údajů Wi-Fi
onboarding-connect_tracker-connection_status-connected = Připojeno k Wi-Fi
onboarding-connect_tracker-connection_status-error = Nelze se připojit k Wi-Fi
onboarding-connect_tracker-connection_status-start_connecting = Hledání trackerů
onboarding-connect_tracker-connection_status-handshake = Připojeno k Serveru
onboarding-connect_tracker-connection_status-connection_error = Nelze se připojit k síti Wi-Fi
# $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",
@@ -510,6 +501,13 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = Připojil jsem všechny své trackery
## Tracker calibration tutorial
onboarding-calibration_tutorial-status-success = Super!
## Tracker assignment tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = Zpět na přihlašovací údaje Wi-Fi
@@ -527,6 +525,12 @@ onboarding-assign_trackers-assigned =
onboarding-assign_trackers-advanced = Zobrazit pokročilá místa přiřazení
onboarding-assign_trackers-next = Přiřadil jsem všechny trackery
## Tracker assignment warnings
## Tracker mounting method choose
## Tracker manual mounting setup
onboarding-manual_mounting-back = Zpět na Enter VR
@@ -556,6 +560,9 @@ onboarding-automatic_mounting-put_trackers_on-title = Nasaďte si trackery
onboarding-automatic_mounting-put_trackers_on-description = Pro kalibraci rotace montáže použijeme právě přiřazené trackery. Nasaďte všechny trackery, na obrázku vpravo vidíte, které jsou které.
onboarding-automatic_mounting-put_trackers_on-next = Mám nasazené všechny trackery
## Tracker proportions method choose
## Tracker manual proportions setup
onboarding-manual_proportions-back = Zpět na Reset tutoriál
@@ -573,22 +580,14 @@ onboarding-automatic_proportions-prev_step = Předchozí krok
onboarding-automatic_proportions-put_trackers_on-title = Nasaďte si trackery
onboarding-automatic_proportions-put_trackers_on-description = Pro kalibraci proporcí použijeme trackery, které jste právě přiřadili. Nasaďte si trackery, na obrázku vpravo vidíte, která jsou která.
onboarding-automatic_proportions-put_trackers_on-next = Mám nasazené všechny trackery
onboarding-automatic_proportions-preparation-title = Příprava
onboarding-automatic_proportions-preparation-description = Umístěte židli přímo za sebe do herního prostoru. Buďte připraveni se během nastavení autobonu posadit.
onboarding-automatic_proportions-preparation-next = Jsem před židlí
onboarding-automatic_proportions-start_recording-title = Připravte se hýbat
onboarding-automatic_proportions-start_recording-description = Nyní budeme nahrávat některé konkrétní pózy a pohyby. Tyto se zobrazí na další obrazovce. Po stisknutí tlačítka buďte připraveni začít!
onboarding-automatic_proportions-start_recording-next = Spustit nahrávání
onboarding-automatic_proportions-recording-title = ZÁZN
onboarding-automatic_proportions-recording-description-p0 = Probíhá nahrávání...
onboarding-automatic_proportions-recording-description-p1 = Proveďte níže uvedené pohyby:
onboarding-automatic_proportions-recording-steps-0 = Párkrát ohněte kolena.
onboarding-automatic_proportions-recording-steps-1 = Posaďte se na židli a pak se postavte.
onboarding-automatic_proportions-recording-steps-2 = Natočte horní část těla doleva a pak se ohněte doprava.
onboarding-automatic_proportions-recording-steps-3 = Natočte horní část těla doprava a pak se ohněte doleva.
onboarding-automatic_proportions-recording-steps-4 = Hýbejte se, dokud časovač neskončí.
onboarding-automatic_proportions-recording-processing = Zpracování výsledku
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 15)
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =
{ $time ->
[one] Zbývá 1 sekunda
@@ -607,3 +606,6 @@ onboarding-automatic_proportions-done-description = Kalibrace proporcí vašeho
## Home
home-no_trackers = Nebyly zjištěny ani přiřazeny žádné trackery
## Status system

View File

@@ -61,7 +61,7 @@ skeleton_bone-HIP_OFFSET = Hüftversatz
skeleton_bone-HIPS_WIDTH = Hüftbreite
skeleton_bone-leg_group = Beinlänge
skeleton_bone-UPPER_LEG = Linker Oberschenkellänge
skeleton_bone-LOWER_LEG = Linker Unterschenkellänge
skeleton_bone-LOWER_LEG = Unterschenkellänge
skeleton_bone-FOOT_LENGTH = Fußlänge
skeleton_bone-FOOT_SHIFT = Fußverschiebung
skeleton_bone-SKELETON_OFFSET = Skelettversatz
@@ -328,10 +328,10 @@ settings-general-fk_settings-leg_tweak-skating_correction = Rutschkorrektur
settings-general-fk_settings-leg_tweak-toe_snap = Zehenausrichtung
settings-general-fk_settings-leg_tweak-foot_plant = Fußkorrektur
settings-general-fk_settings-leg_tweak-skating_correction-amount = Rutschkorrekturstärke
settings-general-fk_settings-leg_tweak-skating_correction-description = Die Rutschkorrektur korrigiert das Wegrutschen des Fußes, kann aber die Genauigkeit bestimmter Bewegungsmuster verringern. Wenn du dies aktivierst, stellen sicher, dass du im Spiel dein Tracking vollständig zurücksetzt und neu kalibrierst.
settings-general-fk_settings-leg_tweak-floor_clip-description = Bodenclip kann das Clipping durch den Boden reduzieren oder sogar eliminieren. Wenn du dies aktivierst, stelle sicher, dass du im Spiel dein Tracking vollständig zurücksetzt und neu kalibrierst.
settings-general-fk_settings-leg_tweak-toe_snap-description = Zehen-Ausrichtung versucht, die Rotation deiner Füße zu erraten, wenn keine Fuß-Tracker verwendet werden.
settings-general-fk_settings-leg_tweak-foot_plant-description = Fußkorrektur richtet deine Füße parallel zum Boden aus, wenn sie den Boden berühren.
settings-general-fk_settings-leg_tweak-skating_correction-description = Die Rutschkorrektur korrigiert das Wegrutschen des Fußes, kann aber die Genauigkeit bestimmter Bewegungsmuster verringern. Wenn Sie dies aktivieren, stellen Sie sicher, dass Sie im Spiel Ihr Tracking vollständig zurücksetzten und neu kalibrieren.
settings-general-fk_settings-leg_tweak-floor_clip-description = Bodenclip kann das Clipping durch den Boden reduzieren oder sogar eliminieren. Wenn Sie dies aktivieren, stellen Sie sicher, dass Sie im Spiel Ihr Tracking vollständig zurücksetzten und neu kalibrieren.
settings-general-fk_settings-leg_tweak-toe_snap-description = Zehen-Ausrichtung versucht, die Rotation Ihrer Füße zu erraten, wenn keine Fuß-Tracker verwendet werden.
settings-general-fk_settings-leg_tweak-foot_plant-description = Fußkorrektur richtet Ihre Füße parallel zum Boden aus, wenn sie den Boden berühren.
settings-general-fk_settings-leg_fk = Beintracking
settings-general-fk_settings-arm_fk = Arm-Tracking
settings-general-fk_settings-arm_fk-description = Ändern Sie die Art und Weise, wie die Arme berechnet werden.
@@ -364,7 +364,7 @@ settings-general-gesture_control-fullResetEnabled = Vollständiger Reset durch A
settings-general-gesture_control-fullResetDelay = Verzögerung für einen vollständigen Reset
settings-general-gesture_control-fullResetTaps = Antipp-Anzahl für einen vollständigen Reset
settings-general-gesture_control-mountingResetEnabled = Antippen für Befestigungs-Reset
settings-general-gesture_control-mountingResetDelay = Befestigungs-Reset-Verzügerung
settings-general-gesture_control-mountingResetDelay = Befestigungs-Reset-Verzögerung
settings-general-gesture_control-mountingResetTaps = Anzahl für Befestigungs-Reset
## Interface settings
@@ -522,7 +522,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Zurück zur Trackerausrichtung
onboarding-reset_tutorial = Tutorial neustarten
onboarding-reset_tutorial-description = Diese Funktion ist noch nicht fertig, drücken Sie einfach auf Fortsetzen
onboarding-reset_tutorial-explanation = Während Sie Ihre Tracker verwenden, können sie aufgrund der IMU-Gierdrift oder weil Sie sie physisch bewegt haben, aus der Ausrichtung geraten. Sie haben mehrere Möglichkeiten, dies zu beheben.
onboarding-reset_tutorial-skip = Schritt überspringen
# Cares about multiline
onboarding-reset_tutorial-0 =
@@ -694,11 +694,11 @@ onboarding-choose_mounting = Welche Kalibrierungsmethode ist zu verwenden?
onboarding-choose_mounting-description = Die Montageausrichtung korrigiert die Platzierung von Trackern am Körper.
onboarding-choose_mounting-auto_mounting = Befestigung automatisch ermitteln
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Empfohlen
onboarding-choose_mounting-auto_mounting-description = Dadurch werden die Befestigungsausrichtungen für alle deine Tracker automatisch aus 2 Posen erkannt
onboarding-choose_mounting-auto_mounting-label = Experimentell
onboarding-choose_mounting-auto_mounting-description = Dadurch werden die Befestigungsausrichtungen für alle Ihrer Tracker automatisch aus 2 Posen erkannt
onboarding-choose_mounting-manual_mounting = Manuelle Befestigungsposition
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Wenn du weißt, was du tust
onboarding-choose_mounting-manual_mounting-label = Empfohlen
onboarding-choose_mounting-manual_mounting-description = Auf diese Weise können Sie die Montagerichtung für jeden Tracker manuell auswählen
## Tracker manual mounting setup
@@ -720,7 +720,7 @@ onboarding-automatic_mounting-prev_step = Vorheriger Schritt
onboarding-automatic_mounting-done-title = Tracker Rotation kalibriert.
onboarding-automatic_mounting-done-description = Ihre Rotations-Kalibrierung ist abgeschlossen!
onboarding-automatic_mounting-done-restart = Zurück zum Start
onboarding-automatic_mounting-mounting_reset-title = Drehungs-Reset
onboarding-automatic_mounting-mounting_reset-title = Befestigungs-Reset
onboarding-automatic_mounting-mounting_reset-step-0 = 1. Beugen Sie sich in die "Skifahren"-Pose mit gebeugten Beinen, geneigtem Oberkörper und gebeugten Armen.
onboarding-automatic_mounting-mounting_reset-step-1 = 2. Drücken Sie die Schaltfläche "Befestigungs-Reset" und warten Sie 3 Sekunden, bevor die Drehungen der Tracker gesetzt werden.
onboarding-automatic_mounting-preparation-title = Vorbereitung
@@ -739,7 +739,7 @@ onboarding-choose_proportions-auto_proportions-subtitle = Empfohlen
onboarding-choose_proportions-auto_proportions-description = Dadurch werden Ihre Proportionen erraten, indem Stichproben Ihrer Bewegungen verrechnet werden
onboarding-choose_proportions-manual_proportions = Manuelle Körperproportionen
onboarding-choose_proportions-manual_proportions-description = Auf diese Weise können Sie Ihre Proportionen manuell anpassen, indem Sie diese direkt ändern
onboarding-choose_proportions-save = Proportionen speichern
onboarding-choose_proportions-export = Proportionen exportieren
onboarding-choose_proportions-file_type = Körperproportions-Datei
## Tracker manual proportions setup

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,6 +10,9 @@
websocket-connecting = Σύνδεση με τον διακομιστή
websocket-connection_lost = Η σύνδεση μεταξύ του διακομιστή χάθηκε. Προσπαθώντας να επανασυνδεθεί...
## Update notification
## Tips
tips-find_tracker = Δεν είστε σίγουροι ποιος ανιχνευτής είναι ποιος; Κουνήστε έναν ανιχνευτή και θα επισημάνει το αντίστοιχο στοιχείο.
@@ -32,7 +32,7 @@ body_part-RIGHT_LOWER_LEG = Δεξιός αστράγαλος
body_part-RIGHT_FOOT = Δεξί πόδι
body_part-CHEST = Στήθος
body_part-WAIST = Μέση
body_part-HIP = γοφοί
body_part-HIP = Γοφοί
body_part-LEFT_SHOULDER = Αριστερός ώμος
body_part-LEFT_UPPER_ARM = Αριστερό μπράτσο
body_part-LEFT_LOWER_ARM = Αριστερό αγγόνας
@@ -68,7 +68,6 @@ skeleton_bone-ELBOW_OFFSET = Μετατόπιση αγκώνα
reset-reset_all = Επαναφορά όλων των αναλογιών
reset-full = Επαναφορά
reset-mounting = Επαναφορά τοποθέτησης
reset-quick = Γρήγορη επαναφορά
## Serial detection stuff
@@ -89,11 +88,14 @@ navbar-mounting = Βαθμονόμηση τοποθέτησης
navbar-onboarding = Οδηγός εγκατάστασης
navbar-settings = Ρυθμίσεις
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Εγγραφή BVH
bvh-recording = Γίνεται εγγραφή...
## Tracking pause
## Widget: Overlay settings
widget-overlay = Υπέρθεση
@@ -191,7 +193,32 @@ body_assignment_menu-unassign_tracker = Μη εκχωρημένος ανιχνε
## Tracker assignment menu
# A -translation_key (with a dash in the front) means that it's a label.
# It can only be used in the translation file, it's nice for reusing names and that kind of stuff.
#
# We are using it here because english doesn't require changing the text in each case but
# maybe your language does.
-tracker_selection-part = Ποιος ιχνηλάτης πρέπει να αντιστοιχίσετε στο σας
tracker_selection_menu-NONE = Ποιος ανιχνευτή θέλετε να είναι μη εκχωρημένος;
tracker_selection_menu-HEAD = { -tracker_selection-part } κεφάλι;
tracker_selection_menu-NECK = { -tracker_selection-part } λαιμός;
tracker_selection_menu-RIGHT_SHOULDER = { -tracker_selection-part } δεξιός ώμος;
tracker_selection_menu-RIGHT_UPPER_ARM = { -tracker_selection-part } δεξιό μπράτσο?
tracker_selection_menu-RIGHT_LOWER_ARM = { -tracker_selection-part } δεξί αγγόνας?
tracker_selection_menu-RIGHT_HAND = { -tracker_selection-part } δεξί χέρι?
tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } δεξιός μηρός?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } δεξιός αστράγαλος?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } δεξί πόδι?
tracker_selection_menu-CHEST = { -tracker_selection-part } στήθος?
tracker_selection_menu-WAIST = { -tracker_selection-part } μέση?
tracker_selection_menu-HIP = { -tracker_selection-part } γοφοί?
tracker_selection_menu-LEFT_SHOULDER = { -tracker_selection-part } αριστερός ώμος?
tracker_selection_menu-LEFT_UPPER_ARM = { -tracker_selection-part } αριστερό μπράτσο?
tracker_selection_menu-LEFT_LOWER_ARM = { -tracker_selection-part } αριστερό αγγόνας?
tracker_selection_menu-LEFT_HAND = { -tracker_selection-part } αριστερό χέρι?
tracker_selection_menu-LEFT_UPPER_LEG = { -tracker_selection-part } αριστερός μηρός?
tracker_selection_menu-LEFT_LOWER_LEG = { -tracker_selection-part } αριστερός αστράγαλος?
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } αριστερό πόδι?
## Mounting menu
@@ -201,6 +228,11 @@ tracker_selection_menu-NONE = Ποιος ανιχνευτή θέλετε να ε
## SteamVR settings
settings-general-steamvr = SteamVR
settings-general-steamvr-trackers-waist = Μέση
settings-general-steamvr-trackers-chest = Στήθος
settings-general-steamvr-trackers-feet = Πόδια
settings-general-steamvr-trackers-hands = Χέρια
## Tracker mechanics
@@ -222,6 +254,11 @@ tracker_selection_menu-NONE = Ποιος ανιχνευτή θέλετε να ε
## OSC VRChat settings
settings-osc-vrchat-network-trackers-chest = Στήθος
settings-osc-vrchat-network-trackers-feet = Πόδια
## VMC OSC settings
## Setup/onboarding menu
@@ -244,18 +281,30 @@ tracker_selection_menu-NONE = Ποιος ανιχνευτή θέλετε να ε
## Tracker connection setup
## Tracker calibration tutorial
## Tracker assignment tutorial
## Tracker assignment setup
## Tracker assignment warnings
## Tracker mounting method choose
## Tracker manual mounting setup
## Tracker automatic mounting setup
## Tracker proportions method choose
## Tracker manual proportions setup
@@ -264,3 +313,6 @@ tracker_selection_menu-NONE = Ποιος ανιχνευτή θέλετε να ε
## Home
## Status system

View File

@@ -31,6 +31,7 @@ body_part-RIGHT_HAND = Right hand
body_part-RIGHT_UPPER_LEG = Right thigh
body_part-RIGHT_LOWER_LEG = Right ankle
body_part-RIGHT_FOOT = Right foot
body_part-UPPER_CHEST = Upper chest
body_part-CHEST = Chest
body_part-WAIST = Waist
body_part-HIP = Hip
@@ -41,14 +42,16 @@ body_part-LEFT_HAND = Left hand
body_part-LEFT_UPPER_LEG = Left thigh
body_part-LEFT_LOWER_LEG = Left ankle
body_part-LEFT_FOOT = Left foot
body_part-ACCESSORY = Accessory
## Proportions
skeleton_bone-NONE = None
skeleton_bone-HEAD = Head Shift
skeleton_bone-NECK = Neck Length
skeleton_bone-torso_group = Torso length
skeleton_bone-CHEST = Chest Length
skeleton_bone-UPPER_CHEST = Upper Chest Length
skeleton_bone-CHEST_OFFSET = Chest Offset
skeleton_bone-CHEST = Chest Length
skeleton_bone-WAIST = Waist Length
skeleton_bone-HIP = Hip Length
skeleton_bone-HIP_OFFSET = Hip Offset
@@ -107,6 +110,9 @@ widget-overlay-is_mirrored_label = Display Overlay as Mirror
## Widget: Drift compensation
widget-drift_compensation-clear = Clear drift compensation
## Widget: Clear Reset Mounting
widget-clear_mounting = Clear reset mounting
## Widget: Developer settings
widget-developer_mode = Developer Mode
widget-developer_mode-high_contrast = High contrast
@@ -145,9 +151,15 @@ tracker-table-column-url = URL
## Tracker rotation
tracker-rotation-front = Front
tracker-rotation-front_left = Front-Left
tracker-rotation-front_right = Front-Right
tracker-rotation-left = Left
tracker-rotation-right = Right
tracker-rotation-back = Back
tracker-rotation-back_left = Back-Left
tracker-rotation-back_right = Back-Right
tracker-rotation-custom = Custom
tracker-rotation-overriden = (overriden by mounting reset)
## Tracker information
tracker-infos-manufacturer = Manufacturer
@@ -207,6 +219,7 @@ tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } right thigh
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } right ankle?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } right foot?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } right controller?
tracker_selection_menu-UPPER_CHEST = { -tracker_selection-part } upper chest?
tracker_selection_menu-CHEST = { -tracker_selection-part } chest?
tracker_selection_menu-WAIST = { -tracker_selection-part } waist?
tracker_selection_menu-HIP = { -tracker_selection-part } hip?
@@ -246,6 +259,8 @@ settings-sidebar-osc_router = OSC router
settings-sidebar-osc_trackers = VRChat OSC Trackers
settings-sidebar-utils = Utilities
settings-sidebar-serial = Serial console
settings-sidebar-appearance = Appearance
settings-sidebar-notifications = Notifications
## SteamVR settings
settings-general-steamvr = SteamVR
@@ -311,11 +326,23 @@ settings-general-fk_settings-leg_fk = Leg tracking
settings-general-fk_settings-arm_fk = Arm tracking
settings-general-fk_settings-arm_fk-description = Force arms to be tracked from the HMD even if positional hand data is available.
settings-general-fk_settings-arm_fk-force_arms = Force arms from HMD
settings-general-fk_settings-skeleton_settings = Skeleton settings
settings-general-fk_settings-skeleton_settings-toggles = Skeleton toggles
settings-general-fk_settings-skeleton_settings-description = Toggle skeleton settings on or off. It is recommended to leave these on.
settings-general-fk_settings-skeleton_settings-extended_spine = Extended spine
settings-general-fk_settings-skeleton_settings-extended_pelvis = Extended pelvis
settings-general-fk_settings-skeleton_settings-extended_knees = Extended knee
settings-general-fk_settings-skeleton_settings-extended_spine_model = Extended spine model
settings-general-fk_settings-skeleton_settings-extended_pelvis_model = Extended pelvis model
settings-general-fk_settings-skeleton_settings-extended_knees_model = Extended knee model
settings-general-fk_settings-skeleton_settings-ratios = Skeleton ratios
settings-general-fk_settings-skeleton_settings-ratios-description = Change the values of skeleton settings. You may need to adjust your proportions after changing these.
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_hip = Impute waist from chest to hip
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_legs = Impute waist from chest to legs
settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = Impute hip from chest to legs
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Impute hip from waist to legs
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Average the hip's yaw and roll with the legs'
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Average the knee trackers' yaw and roll with the ankles'
settings-general-fk_settings-self_localization-title = Mocap mode
settings-general-fk_settings-self_localization-description = Mocap Mode allows the skeleton to roughly track its own position without a headset or other trackers. Note that this requires feet and head trackers to work and is still experimental.
settings-general-fk_settings-vive_emulation-title = Vive emulation
settings-general-fk_settings-vive_emulation-description = Emulate the waist tracker problems that Vive trackers have. This is a joke and makes tracking worse.
settings-general-fk_settings-vive_emulation-label = Enable Vive emulation
@@ -323,13 +350,19 @@ settings-general-fk_settings-vive_emulation-label = Enable Vive emulation
## Gesture control settings (tracker tapping)
settings-general-gesture_control = Gesture control
settings-general-gesture_control-subtitle = Tap based resets
settings-general-gesture_control-description = Allows for resets to be triggered by tapping a tracker. The tracker highest up on your torso is used for Yaw Reset, the tracker highest up on your left leg is used for Full Reset, and the tracker highest up on your right leg is used for Mounting Reset. It should be mentioned that taps must happen within 0.6 seconds to be registered.
settings-general-gesture_control-description = Allows for resets to be triggered by tapping a tracker. The tracker highest up on your torso is used for Yaw Reset, the tracker highest up on your left leg is used for Full Reset, and the tracker highest up on your right leg is used for Mounting Reset. Taps must occur within the time limit of 0.3 seconds times the number of taps to be recognized.
# This is a unit: 3 taps, 2 taps, 1 tap
# $amount (Number) - Amount of taps (touches to the tracker's case)
settings-general-gesture_control-taps = { $amount ->
[one] 1 tap
*[other] { $amount } taps
}
# This is a unit: 3 trackers, 2 trackers, 1 tracker
# $amount (Number) - Amount of trackers
settings-general-gesture_control-trackers = { $amount ->
[one] 1 tracker
*[other] { $amount } trackers
}
settings-general-gesture_control-yawResetEnabled = Enable tap to yaw reset
settings-general-gesture_control-yawResetDelay = Yaw reset delay
settings-general-gesture_control-yawResetTaps = Taps for yaw reset
@@ -339,23 +372,37 @@ settings-general-gesture_control-fullResetTaps = Taps for full reset
settings-general-gesture_control-mountingResetEnabled = Enable tap to reset mounting
settings-general-gesture_control-mountingResetDelay = Mounting reset delay
settings-general-gesture_control-mountingResetTaps = Taps for mounting reset
# The number of trackers that can have higher acceleration before a tap is rejected
settings-general-gesture_control-numberTrackersOverThreshold = Trackers over threshold
settings-general-gesture_control-numberTrackersOverThreshold-description = Increase this value if tap detection is not working. Do not increase it above what is needed to make tap detection work as it would cause more false positives.
## Interface settings
settings-general-interface = Interface
## Appearance settings
settings-interface-appearance = Appearance
settings-general-interface-dev_mode = Developer Mode
settings-general-interface-dev_mode-description = This mode can be useful if you need in-depth data or to interact with connected trackers on a more advanced level.
settings-general-interface-dev_mode-label = Developer Mode
settings-general-interface-serial_detection = Serial device detection
settings-general-interface-serial_detection-description = This option will show a pop-up every time you plug a new serial device that could be a tracker. It helps improving the setup process of a tracker.
settings-general-interface-serial_detection-label = Serial device detection
settings-general-interface-feedback_sound = Feedback sound
settings-general-interface-feedback_sound-description = This option will play a sound when a reset is triggered
settings-general-interface-feedback_sound-label = Feedback sound
settings-general-interface-feedback_sound-volume = Feedback sound volume
settings-general-interface-theme = Color theme
settings-general-interface-lang = Select language
settings-general-interface-lang-description = Change the default language you want to use.
settings-general-interface-lang-placeholder = Select the language to use
# Keep the font name untranslated
settings-interface-appearance-font = GUI font
settings-interface-appearance-font-description = This changes the font used by the interface.
settings-interface-appearance-font-placeholder = Default font
settings-interface-appearance-font-os_font = OS font
settings-interface-appearance-font-slime_font = Default font
settings-interface-appearance-font_size = Base font scaling
settings-interface-appearance-font_size-description = This affects the font size of the whole interface except this settings panel.
## Notification settings
settings-interface-notifications = Notifications
settings-general-interface-serial_detection = Serial device detection
settings-general-interface-serial_detection-description = This option will show a pop-up every time you plug a new serial device that could be a tracker. It helps improving the setup process of a tracker.
settings-general-interface-serial_detection-label = Serial device detection
settings-general-interface-feedback_sound = Feedback sound
settings-general-interface-feedback_sound-description = This option will play a sound when a reset is triggered.
settings-general-interface-feedback_sound-label = Feedback sound
settings-general-interface-feedback_sound-volume = Feedback sound volume
## Serial settings
settings-serial = Serial Console
@@ -407,6 +454,8 @@ settings-osc-vrchat = VRChat OSC Trackers
settings-osc-vrchat-description =
Change VRChat-specific settings to receive HMD data and send
tracker data for FBT without SteamVR (ex. Quest standalone).
This also allows you to receive trackers under the OSCTrackers standard.
This will also send accessory trackers' rotations for custom avatars.
settings-osc-vrchat-enable = Enable
settings-osc-vrchat-enable-description = Toggle the sending and receiving of data.
settings-osc-vrchat-enable-label = Enable
@@ -434,12 +483,12 @@ settings-osc-vmc = Virtual Motion Capture
# This cares about multilines
settings-osc-vmc-description =
Change settings specific to the VMC (Virtual Motion Capture) protocol
to send SlimeVR's bone data and receive bone data from other apps.
to send and received bone and tracker data from and to other apps.
settings-osc-vmc-enable = Enable
settings-osc-vmc-enable-description = Toggle the sending and receiving of data.
settings-osc-vmc-enable-label = Enable
settings-osc-vmc-network = Network ports
settings-osc-vmc-network-description = Set the ports for listening and sending data via VMC
settings-osc-vmc-network-description = Set the ports for listening and sending data via VMC.
settings-osc-vmc-network-port_in =
.label = Port In
.placeholder = Port in (default: 39540)
@@ -447,10 +496,10 @@ settings-osc-vmc-network-port_out =
.label = Port Out
.placeholder = Port out (default: 39539)
settings-osc-vmc-network-address = Network address
settings-osc-vmc-network-address-description = Choose which address to send out data at via VMC
settings-osc-vmc-network-address-description = Choose which address to send out data at via VMC.
settings-osc-vmc-network-address-placeholder = IPV4 address
settings-osc-vmc-vrm = VRM Model
settings-osc-vmc-vrm-description = Load a VRM model to allow head anchor and enable a higher compatibility with other applications
settings-osc-vmc-vrm-description = Load a VRM model to allow head anchor and enable a higher compatibility with other applications.
settings-osc-vmc-vrm-model_unloaded = No model loaded
settings-osc-vmc-vrm-model_loaded = { $titled ->
*[false] Untitled model loaded
@@ -491,7 +540,7 @@ onboarding-wifi_creds-password =
## Mounting setup
onboarding-reset_tutorial-back = Go Back to Mounting calibration
onboarding-reset_tutorial = Reset tutorial
onboarding-reset_tutorial-description = While you use your trackers they might get out of alignment because of IMU yaw drift, or because you might have moved them physically. You have several ways to fix this.
onboarding-reset_tutorial-explanation = While you use your trackers they might get out of alignment because of IMU yaw drift, or because you might have moved them physically. You have several ways to fix this.
onboarding-reset_tutorial-skip = Skip step
# Cares about multiline
onboarding-reset_tutorial-0 = Tap { $taps } times the highlighted tracker for triggering yaw reset.
@@ -649,11 +698,11 @@ onboarding-choose_mounting = What mounting calibration method to use?
onboarding-choose_mounting-description = Mounting orientation corrects for the placement of trackers on your body.
onboarding-choose_mounting-auto_mounting = Automatic mounting
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Experimental
onboarding-choose_mounting-auto_mounting-label = Experimental
onboarding-choose_mounting-auto_mounting-description = This will automatically detect the mounting directions for all of your trackers from 2 poses
onboarding-choose_mounting-manual_mounting = Manual mounting
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Recommended
onboarding-choose_mounting-manual_mounting-label = Recommended
onboarding-choose_mounting-manual_mounting-description = This will let you choose the mounting direction manually for each tracker
@@ -692,12 +741,15 @@ onboarding-choose_proportions-description = Body proportions are used to know th
onboarding-choose_proportions-auto_proportions = Automatic proportions
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Recommended
onboarding-choose_proportions-auto_proportions-description = This will guess your proportions by recording a sample of your movements and passing it through an algorithm
onboarding-choose_proportions-auto_proportions-descriptionv2 =
This will guess your proportions by recording a sample of your movements and passing it through an algorithm.
<b>This requires having your HMD connected to SlimeVR!</b>
onboarding-choose_proportions-manual_proportions = Manual proportions
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = For small touches
onboarding-choose_proportions-manual_proportions-description = This will let you adjust your proportions manually by modifying them directly
onboarding-choose_proportions-save = Export proportions
onboarding-choose_proportions-export = Export proportions
onboarding-choose_proportions-file_type = Body proportions file
## Tracker manual proportions setup
@@ -726,6 +778,18 @@ onboarding-automatic_proportions-requirements-description =
Your trackers and headset are working properly within the SlimeVR server.
Your headset is reporting positional data to the SlimeVR server (this generally means having SteamVR running and connected to SlimeVR using SlimeVR's SteamVR driver).
onboarding-automatic_proportions-requirements-next = I have read the requirements
onboarding-automatic_proportions-check_height-title = Check your height
onboarding-automatic_proportions-check_height-description = We use your height as a basis of our measurements by using the HMD's height as an approximation of your actual height, but it's better to check if they are right yourself!
# All the text is in bold!
onboarding-automatic_proportions-check_height-calculation_warning = Please press the button while standing <u>upright</u> to calculate your height. You have 3 seconds after you press the button!
onboarding-automatic_proportions-check_height-fetch_height = I'm standing!
# Context is that the height is unknown
onboarding-automatic_proportions-check_height-unknown = Unknown
# Shows an element below it
onboarding-automatic_proportions-check_height-height = Your height is
# Shows an element below it
onboarding-automatic_proportions-check_height-hmd_height = And HMD height is
onboarding-automatic_proportions-check_height-next_step = They are fine
onboarding-automatic_proportions-start_recording-title = Get ready to move
onboarding-automatic_proportions-start_recording-description = We're now going to record some specific poses and moves. These will be prompted in the next screen. Be ready to start when the button is pressed!
onboarding-automatic_proportions-start_recording-next = Start Recording
@@ -754,6 +818,10 @@ onboarding-automatic_proportions-verify_results-redo = Redo recording
onboarding-automatic_proportions-verify_results-confirm = They're correct
onboarding-automatic_proportions-done-title = Body measured and saved.
onboarding-automatic_proportions-done-description = Your body proportions' calibration is complete!
onboarding-automatic_proportions-error_modal =
<b>Warning:</b> An error was found while estimating proportions!
Please <docs>check the docs</docs> or join our <discord>Discord</discord> for help ^_^
onboarding-automatic_proportions-error_modal-confirm = Understood!
## Home
home-no_trackers = No trackers detected or assigned

View File

@@ -532,20 +532,20 @@ onboarding-reset_tutorial-skip = Saltar paso
# Cares about multiline
onboarding-reset_tutorial-0 =
Toca { $taps } veces el tracker resaltado para activar el reinicio horizontal.
Esto va a hacer que tus sensores miren para la misma dirección que tu HMD.
# Cares about multiline
onboarding-reset_tutorial-1 =
Toca { $taps } veces el tracker resaltado para activar el reinicio completo.
Se requiere que estas de forma parada (pose en i). Esto tiene un delay de 3 segundos (configurable) antes de que actualmente suceda.
Esto reinicia completamente la posición y rotación de todos tus sensores, debería de arreglar la mayoría de tus problemas.
# Cares about multiline
onboarding-reset_tutorial-2 =
Toca { $taps } veces el tracker resaltado para activar el reinicio de montura.
El reinicio de montura ayuda en como tus sensores están puestos en tu cuerpo, ya que si los movistes o cambiaste para donde están orientados bastante, esto debería de ayudar.
Requiere que estas en una pose como que estás esquiando, como se muestra en el tutorial de montura automática y tenes un retraso de 3 segundos (configurable) antes de que actualmente suceda.
## Setup start
@@ -758,7 +758,7 @@ onboarding-choose_proportions-manual_proportions = Proporciones manuales
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = Para toques pequeños
onboarding-choose_proportions-manual_proportions-description = Esto te permitirá ajustar tus proporciones manualmente de forma directa
onboarding-choose_proportions-save = Exportar proporciones
onboarding-choose_proportions-export = Exportar proporciones
onboarding-choose_proportions-file_type = Archivo de proporciones del cuerpo
## Tracker manual proportions setup

View File

@@ -527,7 +527,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Retourner à l'alignement des capteurs
onboarding-reset_tutorial = Didacticiel de réinitialisation
onboarding-reset_tutorial-description = Cette fonctionnalité n'est pas encore terminée, appuyez simplement sur continuer
onboarding-reset_tutorial-explanation = Pendant que vous utilisez vos capteurs, ils peuvent se désaligner à cause de la dérive horizontale du IMU, ou parce que vous les avez déplacés physiquement. Vous avez plusieurs façons de résoudre ce problème.
onboarding-reset_tutorial-skip = Sauter l'étape
# Cares about multiline
onboarding-reset_tutorial-0 =
@@ -707,11 +707,11 @@ onboarding-choose_mounting = Quelle méthode de calibration de lalignement ut
onboarding-choose_mounting-description = La calibration de l'alignement ajuste pour l'orientation des capteurs sur votre corps.
onboarding-choose_mounting-auto_mounting = Alignement automatique
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Expérimentale
onboarding-choose_mounting-auto_mounting-label = Expérimentale
onboarding-choose_mounting-auto_mounting-description = Ceci permettra de détecter automatiquement la direction de tous vos capteurs à partir de 2 poses
onboarding-choose_mounting-manual_mounting = Alignement manuel
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Recommendée
onboarding-choose_mounting-manual_mounting-label = Recommendée
onboarding-choose_mounting-manual_mounting-description = Ceci vous permettra de choisir la direction de chaque capteur manuellement
## Tracker manual mounting setup
@@ -758,7 +758,7 @@ onboarding-choose_proportions-manual_proportions = Proportions manuelles
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = Pour les retouches
onboarding-choose_proportions-manual_proportions-description = Ceci vous permettra d'ajuster vos proportions manuellement en les modifiant directement
onboarding-choose_proportions-save = Exporter les proportions
onboarding-choose_proportions-export = Exporter les proportions
onboarding-choose_proportions-file_type = Fichier de proportions
## Tracker manual proportions setup

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,6 +10,9 @@
websocket-connecting = מתחבר לשרת
websocket-connection_lost = החיבור לשרת אבד. מנסה להתחבר מחדש
## Update notification
## Tips
tips-find_tracker = לא בטוח איזה חיישן אתה מחזיק? נער את החיישן והתוכנה תסמן לך אותו.
@@ -30,7 +30,6 @@ body_part-RIGHT_HAND = יד ימין
body_part-RIGHT_UPPER_LEG = ירך ימין
body_part-RIGHT_LOWER_LEG = קרסול ימין
body_part-RIGHT_FOOT = רגל ימין
body_part-RIGHT_CONTROLLER = בקר ימני
body_part-CHEST = חזה
body_part-WAIST = מותניים
body_part-HIP = ירך
@@ -41,7 +40,6 @@ body_part-LEFT_HAND = יד שמאל
body_part-LEFT_UPPER_LEG = ירך שמאל
body_part-LEFT_LOWER_LEG = קרסול שמאל
body_part-LEFT_FOOT = רגל שמאל
body_part-LEFT_CONTROLLER = בקר שמאלי
## Proportions
@@ -58,15 +56,12 @@ skeleton_bone-SHOULDERS_DISTANCE = מרחק כתפיים
skeleton_bone-SHOULDERS_WIDTH = רוחב כתפיים
skeleton_bone-UPPER_ARM = אורך זרוע עליונה
skeleton_bone-LOWER_ARM = אורך זרוע תחתונה
skeleton_bone-CONTROLLER_Y = מרחק בקר ציר Y
skeleton_bone-CONTROLLER_Z = מרחק בקר ציר Z
## Tracker reset buttons
reset-reset_all = איפוס כל הפרופורציות
reset-full = איפוס
reset-mounting = איפוס הרכבה
reset-quick = איפוס מהיר
## Serial detection stuff
@@ -87,11 +82,14 @@ navbar-mounting = כיול ההרכבה
navbar-onboarding = אשף ההגדרה
navbar-settings = הגדרות
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = הקלטת BVH
bvh-recording = מקליט...
## Tracking pause
## Widget: Overlay settings
widget-overlay = ממשק Overlay
@@ -256,6 +254,13 @@ settings-general-tracker_mechanics-drift_compensation-max_resets-label = שימ
## OSC VRChat settings
settings-osc-vrchat-network-trackers-chest = חזה
settings-osc-vrchat-network-trackers-knees = ברכיים
settings-osc-vrchat-network-trackers-feet = רגל
settings-osc-vrchat-network-trackers-elbows = מרפקים
## VMC OSC settings
## Setup/onboarding menu
@@ -278,24 +283,35 @@ settings-general-tracker_mechanics-drift_compensation-max_resets-label = שימ
## Tracker connection setup
## Tracker calibration tutorial
## Tracker assignment tutorial
## Tracker assignment setup
## Tracker assignment warnings
## Tracker mounting method choose
## Tracker manual mounting setup
## Tracker automatic mounting setup
## Tracker proportions method choose
## Tracker manual proportions setup
## Tracker automatic proportions setup
onboarding-automatic_proportions-recording-steps-4 = זוז במקום עד שהספירה תסתיים
onboarding-automatic_proportions-recording-processing = מעבד את התוצאה
onboarding-automatic_proportions-verify_results-title = אמת את התוצאות
onboarding-automatic_proportions-verify_results-description = אנא בדוק את התוצאות, האם התוצאות נראות נכון?
@@ -309,3 +325,6 @@ onboarding-automatic_proportions-done-description = תהליך כיול פרופ
## Home
home-no_trackers = לא זוהו או הוקצו חיישנים
## Status system

View File

@@ -12,6 +12,8 @@ websocket-connection_lost = サーバーへの接続が失われました。再
## Update notification
version_update-title = 新しいバージョンが利用可能です:{ $version }
version_update-description = { version_update-update }をクリックすると、SlimeVRインストーラーがダウンロードされます。
version_update-update = アップデート
version_update-close = 閉じる
@@ -19,6 +21,8 @@ version_update-close = 閉じる
tips-find_tracker = どのトラッカーがどれだかわからない?トラッカーを振ると、該当する項目がハイライトされます。
tips-do_not_move_heels = レコーディング中にかかとが動かないように注意しましょう!
tips-file_select = 使用するファイルをドラッグ&ドロップするか、 <u>参照</u>します。
tips-tap_setup = 追跡装置をゆっくり2回軽くタップして選択することができます、メニューから選ぶ必要はありません
## Body parts
@@ -48,12 +52,14 @@ body_part-LEFT_FOOT = 左足先
skeleton_bone-NONE = 無し
skeleton_bone-HEAD = ヘッドシフト
skeleton_bone-NECK = 首長さ
skeleton_bone-CHEST = 胸囲
skeleton_bone-torso_group = 胴体の長さ
skeleton_bone-CHEST_OFFSET = 胸オフセット
skeleton_bone-CHEST = 胸囲
skeleton_bone-WAIST = ウエスト長さ
skeleton_bone-HIP = ヒップ長さ
skeleton_bone-HIP_OFFSET = ヒップオフセット
skeleton_bone-HIPS_WIDTH = ヒップ幅
skeleton_bone-leg_group = 股下の長さ
skeleton_bone-UPPER_LEG = 膝長さ
skeleton_bone-LOWER_LEG = 足長さ
skeleton_bone-FOOT_LENGTH = 足先長さ
@@ -61,8 +67,11 @@ skeleton_bone-FOOT_SHIFT = 足先シフト
skeleton_bone-SKELETON_OFFSET = スケルトンオフセット
skeleton_bone-SHOULDERS_DISTANCE = 肩の距離
skeleton_bone-SHOULDERS_WIDTH = 肩幅
skeleton_bone-arm_group = 腕の長さ
skeleton_bone-UPPER_ARM = 上腕長さ
skeleton_bone-LOWER_ARM = 前腕長さ
skeleton_bone-HAND_Y = 手の距離 Y
skeleton_bone-HAND_Z = 手の距離Z
skeleton_bone-ELBOW_OFFSET = 肘オフセット
## Tracker reset buttons
@@ -98,6 +107,8 @@ bvh-recording = レコーディング中...
## Tracking pause
tracking-unpaused = トラッキング停止
tracking-paused = トラッキング再開
## Widget: Overlay settings
@@ -107,6 +118,7 @@ widget-overlay-is_mirrored_label = オーバーレイをミラーとして表示
## Widget: Drift compensation
widget-drift_compensation-clear = ドリフト補正をクリアする
## Widget: Developer settings
@@ -161,7 +173,11 @@ tracker-infos-manufacturer = メーカ-
tracker-infos-display_name = 表示名
tracker-infos-custom_name = カスタム名称
tracker-infos-url = トラッカーURL
tracker-infos-version = ファームウェアバージョン
tracker-infos-hardware_rev = ハードウエアのリビジョン
tracker-infos-hardware_identifier = ハードウェアID
tracker-infos-imu = 慣性計測センサー
tracker-infos-board_type = メインボード
## Tracker settings
@@ -228,6 +244,9 @@ tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part(body-part: "
tracker_selection_menu-unassigned = 未割り当てのトラッカー
tracker_selection_menu-assigned = 割り当て済みのトラッカー
tracker_selection_menu-dont_assign = 割り当てない
# This line cares about multilines.
# <b>text</b> means that the text should be bold.
tracker_selection_menu-neck_warning = <b>警告:</b>首のトラッカーを締め付けすぎると、頭部の血液循環に危険が生じる可能性があります!
tracker_selection_menu-neck_warning-done = リスクを理解しています
tracker_selection_menu-neck_warning-cancel = キャンセル
@@ -245,6 +264,7 @@ settings-sidebar-fk_settings = FK設定
settings-sidebar-gesture_control = ジェスチャーコントロール
settings-sidebar-interface = インターフェース
settings-sidebar-osc_router = OSCルーター
settings-sidebar-osc_trackers = VRChatOSCトラッカー
settings-sidebar-utils = ユーティリティ
settings-sidebar-serial = シリアルコンソール
@@ -304,6 +324,7 @@ settings-general-fk_settings-leg_tweak-floor_clip = フロアクリップ
# definition - Guesses when each foot is in contact with the ground and uses that information to improve tracking
settings-general-fk_settings-leg_tweak-skating_correction = スケーティング補正
settings-general-fk_settings-leg_tweak-skating_correction-amount = スケーティング補正の強さ
settings-general-fk_settings-leg_fk = 足のトラッキング
settings-general-fk_settings-arm_fk = アームトラッキング
settings-general-fk_settings-arm_fk-description = 腕の追従方法を変更する。
settings-general-fk_settings-arm_fk-force_arms = Force arms from HMD
@@ -350,6 +371,7 @@ settings-general-interface-serial_detection-label = シリアルデバイスの
settings-general-interface-feedback_sound = フィードバック音
settings-general-interface-feedback_sound-label = フィードバック音
settings-general-interface-feedback_sound-volume = フィードバック音量
settings-general-interface-theme = カラーテーマ
settings-general-interface-lang = 言語を選択
settings-general-interface-lang-description = 使用したいデフォルトの言語を変更する
settings-general-interface-lang-placeholder = 使用する言語を選択する
@@ -419,6 +441,7 @@ settings-osc-vrchat-network-address-placeholder = VRChatのIPアドレス
settings-osc-vrchat-network-trackers = トラッカー
settings-osc-vrchat-network-trackers-description = データの送受信を切り替える。
settings-osc-vrchat-network-trackers-chest = 胸
settings-osc-vrchat-network-trackers-hip = 腰
settings-osc-vrchat-network-trackers-knees = 膝
settings-osc-vrchat-network-trackers-feet = 足
settings-osc-vrchat-network-trackers-elbows = 肘
@@ -429,6 +452,12 @@ settings-osc-vmc = バーチャルモーションキャプチャ
settings-osc-vmc-enable = 有効
settings-osc-vmc-enable-label = 有効
settings-osc-vmc-network = ネットワークポート
settings-osc-vmc-network-port_in =
.label = ポートイン
.placeholder = ポートイン(デフォルト:39540)
settings-osc-vmc-network-port_out =
.label = ポートアウト
.placeholder = ポートアウト(デフォルト:39539)
settings-osc-vmc-network-address = ネットワークアドレス
settings-osc-vmc-network-address-placeholder = IPV4アドレス
settings-osc-vmc-vrm = VRMモデル
@@ -438,6 +467,8 @@ settings-osc-vmc-vrm = VRMモデル
onboarding-skip = 設定をスキップする
onboarding-continue = 続ける
onboarding-wip = 実行中
onboarding-setup_warning-skip = セットアップをスキップする
onboarding-setup_warning-cancel = セットアップを続行する
## Wi-Fi setup
@@ -460,7 +491,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = マウントキャリブレーションに戻る
onboarding-reset_tutorial = リセットチュートリアル
onboarding-reset_tutorial-description = この機能は終了していません。続けるを押してください。
onboarding-reset_tutorial-skip = ステップをスキップする
## Setup start
@@ -488,7 +519,12 @@ onboarding-connect_tracker-description-p0 = さあ、楽しい部分に移りま
onboarding-connect_tracker-description-p1 = まだ接続されていないトラッカーたちをUSBポートを通して接続するだけです。
onboarding-connect_tracker-issue-serial = 接続に問題があります!
onboarding-connect_tracker-usb = USBトラッカー
onboarding-connect_tracker-connection_status-none = トラッカーを探しています
onboarding-connect_tracker-connection_status-connecting = Wi-Fiの認証情報を送信中
onboarding-connect_tracker-connection_status-looking_for_server = サーバーを探しています
onboarding-connect_tracker-connection_status-connection_error = Wi-Fiに接続できません
onboarding-connect_tracker-connection_status-could_not_find_server = サーバーが見つかりません
onboarding-connect_tracker-connection_status-done = サーバーに接続されました
# $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",
@@ -504,10 +540,14 @@ onboarding-connect_tracker-next = すべてのトラッカーを接続しまし
## Tracker calibration tutorial
onboarding-calibration_tutorial = IMU校正チュートリアル
onboarding-calibration_tutorial-subtitle = これにより、センサーのドリフトを減らすことが役立ちます
onboarding-calibration_tutorial-status-calibrating = 校正中
## Tracker assignment tutorial
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = ステッカー
## Tracker assignment setup
@@ -530,8 +570,6 @@ onboarding-assign_trackers-next = すべてのトラッカーを割り当てま
## Tracker mounting method choose
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = おすすめされた
## Tracker manual mounting setup
@@ -614,3 +652,10 @@ home-no_trackers = トラッカーを検出できません。もしくは割り
## Status system
status_system-StatusTrackerReset = 一つ以上のトラッカーが調整されていないため、完全なリセットを実行することをお勧めします
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] SlimeVR Feederアプリに接続されていません
*[other] SlimeVRドライバ経由でSteamVRに接続されていません
}
status_system-StatusTrackerError = { $trackerName } トラッカーにエラーが発生しています

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,11 +10,19 @@
websocket-connecting = 서버에 연결하는 중...
websocket-connection_lost = 서버와의 연결이 끊어졌어요. 다시 연결하는 중...
## Update notification
version_update-title = 새로운 버전 발견: { $version }
version_update-description = "{ version_update-update }"를 눌러 설치 프로그램을 다운로드하세요.
version_update-update = 업데이트
version_update-close = 닫기
## Tips
tips-find_tracker = 내 트래커가 어떤 트래커인지 모르시겠다구요? 트래커를 흔들면 해당 항목이 빛날 거예요.
tips-do_not_move_heels = 기록하는 동안 발뒤꿈치가 움직이지 않도록 조심하세요!
tips-file_select = 파일을 <u>열거나,</u> 여기에 드래그&드롭하세요.
tips-tap_setup = 목록에서 트래커를 선택하는 대신 할당할 트래커를 천천히 2번 탭해서 선택할 수 있어요.
## Body parts
@@ -95,11 +100,16 @@ navbar-mounting = 착용 방향 정렬
navbar-onboarding = 설정 마법사
navbar-settings = 설정
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = BVH 기록
bvh-recording = 기록중...
## Tracking pause
tracking-unpaused = 트래킹 일시 중지
tracking-paused = 트래킹 재개
## Widget: Overlay settings
widget-overlay = 오버레이
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = 더 많은 정보 보기
widget-imu_visualizer = 회전
widget-imu_visualizer-rotation_raw = Raw
widget-imu_visualizer-rotation_preview = 미리보기
widget-imu_visualizer-rotation_hide = 숨기기
## Tracker status
@@ -164,6 +175,9 @@ tracker-infos-custom_name = 사용자 정의 이름
tracker-infos-url = 트래커 URL
tracker-infos-version = 펌웨어 버전
tracker-infos-hardware_rev = 하드웨어 리비전
tracker-infos-hardware_identifier = 하드웨어 ID
tracker-infos-imu = IMU 센서
tracker-infos-board_type = 메인보드
## Tracker settings
@@ -252,6 +266,7 @@ settings-sidebar-fk_settings = FK 설정
settings-sidebar-gesture_control = 제스처 제어
settings-sidebar-interface = 인터페이스
settings-sidebar-osc_router = OSC 라우터
settings-sidebar-osc_trackers = VRChat OSC 트래커
settings-sidebar-utils = 유틸리티
settings-sidebar-serial = 시리얼 콘솔
@@ -439,7 +454,7 @@ settings-osc-vrchat-network-address-placeholder = VRChat IP 주소
settings-osc-vrchat-network-trackers = 트래커
settings-osc-vrchat-network-trackers-description = 활성화해서 데이터 송수신
settings-osc-vrchat-network-trackers-chest = Chest
settings-osc-vrchat-network-trackers-waist = Waist
settings-osc-vrchat-network-trackers-hip = 골반
settings-osc-vrchat-network-trackers-knees = Knees
settings-osc-vrchat-network-trackers-feet = Feet
settings-osc-vrchat-network-trackers-elbows = Elbows
@@ -511,7 +526,6 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = 착용 방향 정렬로 돌아가기
onboarding-reset_tutorial = 정렬 튜토리얼
onboarding-reset_tutorial-description = 이 기능은 아직 완성되지 않았어요, 지금은 일단 계속하기를 눌러주세요!
## Setup start
@@ -559,6 +573,22 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = 모든 트래커를 잘 연결했어요
## Tracker calibration tutorial
onboarding-calibration_tutorial = IMU 캘리브레이션 튜토리얼
onboarding-calibration_tutorial-subtitle = 트래커 틀어짐을 줄이는 데 도움이 될 거예요!
onboarding-calibration_tutorial-status-calibrating = 캘리브레이팅
## Tracker assignment tutorial
onboarding-assignment_tutorial = 슬라임 트래커를 착용하기 전에 준비하는 방법
onboarding-assignment_tutorial-first_step = 1. 신체 부위가 적힌 스티커를 가지고 있다면 트래커에 붙여보세요
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = 스티커
onboarding-assignment_tutorial-second_step = 2. 스트랩의 벨크로 테이프 쪽을 그림과 같은 방향으로 유지하면서 스트랩을 트래커에 끼우세요:
onboarding-assignment_tutorial-second_step-continuation = 익스텐션 트래커의 벨크로 테이프는 다음과 같은 방향으로 끼워주세요:
onboarding-assignment_tutorial-done = 스트랩과 스티커를 트래커에 잘 부착했어요!
## Tracker assignment setup
onboarding-assign_trackers-back = Wi-Fi 자격 증명으로 돌아가기
@@ -642,13 +672,11 @@ onboarding-assign_trackers-warning-WAIST =
## Tracker mounting method choose
onboarding-choose_mounting = 착용 방향을 정렬하기 위해 어떤 방법을 사용할래요?
# Multiline text
onboarding-choose_mounting-description = 착용 방향 정렬은 트래커가 몸에 착용된 방향을 찾아 수정하도록 도와줘요.
onboarding-choose_mounting-auto_mounting = 자동으로 방향 설정
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = 권장
onboarding-choose_mounting-auto_mounting-description = 이렇게 하면 두 가지 자세로 모든 트래커의 착용 방향을 자동으로 설정할 수 있어요
onboarding-choose_mounting-manual_mounting = 수동으로 방향 설정
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = 무엇을 하려는 지 알고 있다면요
onboarding-choose_mounting-manual_mounting-description = 이렇게 하면 각 트래커의 착용 방향을 직접 고를 수 있어요
## Tracker manual mounting setup
@@ -682,7 +710,7 @@ onboarding-automatic_mounting-put_trackers_on-next = 모든 트래커를 착용
## Tracker proportions method choose
onboarding-choose_proportions = 신체 비율을 설정하 위해 어떤 방법을 사용할래요?
onboarding-choose_proportions = 신체 비율을 설정하 위해 어떤 방법을 사용할래요?
onboarding-choose_proportions-auto_proportions = 자동으로 비율 설정
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = 권장
@@ -752,3 +780,6 @@ onboarding-automatic_proportions-done-description = 신체 비율 보정이 완
## Home
home-no_trackers = 감지되거나 할당된 트래커가 없어요.
## Status system

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -103,11 +100,16 @@ navbar-mounting = Bevestigings- kalibratie
navbar-onboarding = Setupgids
navbar-settings = Instellingen
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = BVH opnemen
bvh-recording = Opname bezig...
## Tracking pause
tracking-unpaused = Pauzeer tracking
tracking-paused = Herneem tracking
## Widget: Overlay settings
widget-overlay = Overlay
@@ -521,7 +523,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Ga terug naar de bevestigingskalibratie
onboarding-reset_tutorial = Reset tutorial
onboarding-reset_tutorial-description = Deze stap is nog niet afgewerkt, druk gewoon op doorgaan.
onboarding-reset_tutorial-skip = Stap overslaan
## Setup start
@@ -581,6 +583,9 @@ onboarding-calibration_tutorial-status-calibrating = Kalibreren
onboarding-calibration_tutorial-status-success = Aardig!
onboarding-calibration_tutorial-status-error = De tracker werd verplaatst
## Tracker assignment tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = Ga terug naar de instellingen voor WiFi-configuratie
@@ -670,11 +675,11 @@ onboarding-assign_trackers-warning-WAIST =
onboarding-choose_mounting = Welke montagekalibratiemethode moet worden gebruikt?
onboarding-choose_mounting-auto_mounting = Automatische bevestiging
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Aanbevolen
onboarding-choose_mounting-auto_mounting-label = Experimenteel
onboarding-choose_mounting-auto_mounting-description = Dit detecteert automatisch de montagerichtingen voor al uw trackers door middel van 2 poses
onboarding-choose_mounting-manual_mounting = Handmatige bevestiging
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Als je weet wat je doet
onboarding-choose_mounting-manual_mounting-label = Aanbevolen
onboarding-choose_mounting-manual_mounting-description = Hiermee kunt u de montagerichting handmatig kiezen voor elke tracker
## Tracker manual mounting setup
@@ -779,3 +784,6 @@ onboarding-automatic_proportions-done-description = Je kalibratie voor lichaamsv
## Home
home-no_trackers = Geen trackers gedetecteerd of toegewezen
## Status system

View File

@@ -36,6 +36,7 @@ body_part-RIGHT_HAND = Prawa Dłoń
body_part-RIGHT_UPPER_LEG = Prawe Udo
body_part-RIGHT_LOWER_LEG = Prawe Podudzie
body_part-RIGHT_FOOT = Prawa Stopa
body_part-UPPER_CHEST = Górna część klatki piersiowej
body_part-CHEST = Klatka Piersiowa
body_part-WAIST = Talia
body_part-HIP = Biodra
@@ -53,8 +54,9 @@ skeleton_bone-NONE = Brak
skeleton_bone-HEAD = Przesunięcie Głowy
skeleton_bone-NECK = Długość Szyi
skeleton_bone-torso_group = Długość torsu
skeleton_bone-CHEST = Długość Klatki Piersiowej
skeleton_bone-UPPER_CHEST = Górna długość klatki piersiowej
skeleton_bone-CHEST_OFFSET = Przesunięcie Klatki Piersiowej
skeleton_bone-CHEST = Długość Klatki Piersiowej
skeleton_bone-WAIST = Długość Talii
skeleton_bone-HIP = Długość Bioder
skeleton_bone-HIP_OFFSET = Przesunięcie Bioder
@@ -230,6 +232,7 @@ tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } prawe udo?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } prawa kostka?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } prawa stopa?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } prawy kontroler?
tracker_selection_menu-UPPER_CHEST = { -tracker_selection-part } górnej części klatki piersiowej?
tracker_selection_menu-CHEST = { -tracker_selection-part } klatka piersiowa?
tracker_selection_menu-WAIST = { -tracker_selection-part } talia?
tracker_selection_menu-HIP = { -tracker_selection-part } biodro?
@@ -529,7 +532,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Powrót do Konfiguracji Położenia trackerów
onboarding-reset_tutorial = Zresetuj poradnik
onboarding-reset_tutorial-description = Ta funkcja jeszcze nie jest skończona.
onboarding-reset_tutorial-explanation = Podczas korzystania z trackerów mogą się one rozregulować z powodu dryfu odchylenia IMU lub z powodu fizycznego przeniesienia ich. Możesz to naprawić na kilka sposobów.
onboarding-reset_tutorial-skip = Pomiń krok
# Cares about multiline
onboarding-reset_tutorial-0 =
@@ -713,11 +716,11 @@ onboarding-choose_mounting = Jakiej metody kalibracji montażu użyć?
onboarding-choose_mounting-description = Orientacja montażu koryguje umieszczenie trackerów na ciele.
onboarding-choose_mounting-auto_mounting = Automatyczne mocowanie
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Zalecana
onboarding-choose_mounting-auto_mounting-label = Eksperymentalny
onboarding-choose_mounting-auto_mounting-description = To automatycznie wykryje kierunki montażu dla wszystkich twoich trackerów z 2 pozycji
onboarding-choose_mounting-manual_mounting = Montaż ręczny
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Jeśli wiesz, co robisz
onboarding-choose_mounting-manual_mounting-label = Zalecany
onboarding-choose_mounting-manual_mounting-description = Umożliwi to ręczne wybranie kierunku montażu dla każdego trackera
## Tracker manual mounting setup
@@ -764,7 +767,7 @@ onboarding-choose_proportions-manual_proportions = Ręczne proporcje
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = Drobne detale
onboarding-choose_proportions-manual_proportions-description = Umożliwi to ręczne dostosowanie proporcji poprzez ich bezpośrednią modyfikację
onboarding-choose_proportions-save = Zachowaj proporcje
onboarding-choose_proportions-export = Eksportuj proporcje
onboarding-choose_proportions-file_type = Proporcje ciała
## Tracker manual proportions setup

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,10 +10,19 @@
websocket-connecting = Conectando ao servidor
websocket-connection_lost = Conexão perdida com o servidor. Reconectando...
## Update notification
version_update-title = Nova versão disponível: { $version }
version_update-description = Ao clicar em "{ version_update-update }" irá baixar o instalador do SlimeVR para você.
version_update-update = Atualizar
version_update-close = Fechar
## Tips
tips-find_tracker = Não tem certeza qual tracker é qual? Balance o tracker e ele destacará o item correspondente.
tips-do_not_move_heels = Tenha certeza de não mexer seus calcanhares durante a gravação!
tips-file_select = Arraste e solte arquivos para usar, ou <u>pesquise</u>.
tips-tap_setup = Pode tocar lentamente 2 vezes no seu tracker para o escolher em vez de o selecionar no menu.
## Body parts
@@ -70,7 +76,6 @@ skeleton_bone-ELBOW_OFFSET = Compensação do Cotovelo
reset-reset_all = Redefinir todas as proporções
reset-full = Reset
reset-mounting = Reset de Posição
reset-quick = Reset Rápido
## Serial detection stuff
@@ -91,11 +96,14 @@ navbar-mounting = Calibragem de Posição
navbar-onboarding = Assistente de Configuração
navbar-settings = Opções
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Gravar BVH
bvh-recording = Gravando...
## Tracking pause
## Widget: Overlay settings
widget-overlay = Overlay
@@ -297,8 +305,6 @@ settings-general-tracker_mechanics-drift_compensation-max_resets-label = Use at
## FK/Tracking settings
settings-general-fk_settings = Opções de Tracker
settings-general-fk_settings-leg_tweak = Ajustes de perna
settings-general-fk_settings-leg_tweak-description = Atravessar o chão pode reduzir ou até eliminar o clipping(atravessar) com o chão porém pode causar problemas quando ajoelhado. Correção de Deslize corrige o ice skating(deslize dos trackers no chão), porém pode diminuir a precisão de certos padrões de movimento.
# Floor clip:
# why the name - came from the idea of noclip in video games, but is the opposite where clipping to the floor is a desired feature
# definition - Prevents the foot trackers from going lower than they where when a reset was performed
@@ -333,12 +339,6 @@ settings-general-gesture_control-taps =
[one] 1 tap
*[other] { $amount } taps
}
settings-general-gesture_control-quickResetEnabled = Ativar toque para reset rápido
settings-general-gesture_control-quickResetDelay = Delay do reset rápido
settings-general-gesture_control-quickResetTaps = Toques para o reset rápido
settings-general-gesture_control-resetEnabled = Ativar toque para reset
settings-general-gesture_control-resetDelay = Delay do reset
settings-general-gesture_control-resetTaps = Toques para o reset
settings-general-gesture_control-mountingResetEnabled = Toques para o reset de posição
settings-general-gesture_control-mountingResetDelay = Delay do reset de posição
settings-general-gesture_control-mountingResetTaps = Toques para o reset de posição
@@ -426,11 +426,13 @@ settings-osc-vrchat-network-address-placeholder = Endereço de ip do VRChat
settings-osc-vrchat-network-trackers = Trackers
settings-osc-vrchat-network-trackers-description = Ligar ou desligar o envio e recepção de dados.
settings-osc-vrchat-network-trackers-chest = Peito
settings-osc-vrchat-network-trackers-waist = Cintura
settings-osc-vrchat-network-trackers-knees = Joelhos
settings-osc-vrchat-network-trackers-feet = Pés
settings-osc-vrchat-network-trackers-elbows = Cotovelos
## VMC OSC settings
## Setup/onboarding menu
onboarding-skip = Pular configurações
@@ -463,10 +465,6 @@ onboarding-reset_tutorial-description = Esse recurso não está concluído, apen
## Setup start
onboarding-home = Bem vindo ao SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
Trazendo full-body tracking
para todos
onboarding-home-start = Vamos configurar!
## Enter VR part of setup
@@ -511,6 +509,12 @@ onboarding-connect_tracker-connected_trackers =
} connected
onboarding-connect_tracker-next = Eu conectei todos os meus trackers
## Tracker calibration tutorial
## Tracker assignment tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = Voltar para as credenciais de Wi-Fi
@@ -595,6 +599,9 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] Cintura está atribuído, porém a parte do corpo desconhecida não atribuída também precisa ser atribuída!
}
## Tracker mounting method choose
## Tracker manual mounting setup
onboarding-manual_mounting-back = Voltar para entrar no VR
@@ -624,6 +631,9 @@ onboarding-automatic_mounting-put_trackers_on-title = Coloque seus trackers
onboarding-automatic_mounting-put_trackers_on-description = Para calibrar as rotações de posicionamento, usaremos os trackers que você atribuiu. Coloque todos os seus trackers, você pode ver qual é qual na figura na direita.
onboarding-automatic_mounting-put_trackers_on-next = Coloquei todos os meus trackers
## Tracker proportions method choose
## Tracker manual proportions setup
onboarding-manual_proportions-back = Voltar para o tutorial de reset
@@ -641,22 +651,14 @@ onboarding-automatic_proportions-prev_step = Passo anterior
onboarding-automatic_proportions-put_trackers_on-title = Coloque seus trackers
onboarding-automatic_proportions-put_trackers_on-description = Para calibrar suas proporções, usaremos os trackers que você atribuiu. Coloque todos os seus trackers, você pode ver quais são quais na figura à direita.
onboarding-automatic_proportions-put_trackers_on-next = Coloquei todos os meus trackers
onboarding-automatic_proportions-preparation-title = Preparação
onboarding-automatic_proportions-preparation-description = Coloque uma cadeira diretamente atrás de você dentro da sua área de jogo(Play space). Esteja preparado para sentar durante a configuração de autobone.
onboarding-automatic_proportions-preparation-next = Estou em frente a uma cadeira
onboarding-automatic_proportions-start_recording-title = Esteja preparado para se mexer
onboarding-automatic_proportions-start_recording-description = Começaremos a gravar algumas poses e movimentos específicos. Estes serão solicitados na próxima tela. Esteja preparado para começar quando o botão for pressionado!
onboarding-automatic_proportions-start_recording-next = Começar Gravação
onboarding-automatic_proportions-recording-title = GRAVAR
onboarding-automatic_proportions-recording-description-p0 = Gravação em progresso...
onboarding-automatic_proportions-recording-description-p1 = Faça os movimentos apresentados abaixo:
onboarding-automatic_proportions-recording-steps-0 = Dobre os joelhos algumas vezes.
onboarding-automatic_proportions-recording-steps-1 = Sente-se na cadeira e se levante.
onboarding-automatic_proportions-recording-steps-2 = Gire seu tronco para esquerda, e incline para direita.
onboarding-automatic_proportions-recording-steps-3 = Gire seu tronco para direita, e incline para esquerda.
onboarding-automatic_proportions-recording-steps-4 = Mexa-se até o tempo terminar.
onboarding-automatic_proportions-recording-processing = Processando o resultado
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 15)
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =
{ $time ->
[one] 1 second left
@@ -674,3 +676,6 @@ onboarding-automatic_proportions-done-description = Sua calibragem de proporçã
## Home
home-no_trackers = Nenhum tracker detectado ou atribuído
## Status system

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,11 +10,19 @@
websocket-connecting = Подключение к серверу
websocket-connection_lost = Потеряно соединение с сервером. Переподключение...
## Update notification
version_update-title = Доступна новая версия: { $version }
version_update-description = Нажав «{ version_update-update }», вы загрузите установщик SlimeVR.
version_update-update = Обновить
version_update-close = Закрыть
## Tips
tips-find_tracker = Не уверены, какой это трекер? Встряхните его, и трекер выделится в списке.
tips-do_not_move_heels = Убедитесь, что ваши пятки не двигаются во время записи!
tips-file_select = Выберите или перетащите файлы для использования <u>выбрать</u>.
tips-tap_setup = Вы можете медленно нажать 2 раза на свой трекер, чтобы выбрать его, вместо того чтобы выбирать его из меню.
## Body parts
@@ -95,11 +100,16 @@ navbar-mounting = Калибровка крепления
navbar-onboarding = Мастер настройки
navbar-settings = Настройки
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Запись BVH
bvh-recording = Запись...
## Tracking pause
tracking-unpaused = Приостановить отслеживание
tracking-paused = Возобновить отслеживание
## Widget: Overlay settings
widget-overlay = Оверлей
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = Дополнительная информац
widget-imu_visualizer = Вращение
widget-imu_visualizer-rotation_raw = RAW
widget-imu_visualizer-rotation_preview = Предпросмотр
widget-imu_visualizer-rotation_hide = Скрыть
## Tracker status
@@ -164,6 +175,9 @@ tracker-infos-custom_name = Свое имя
tracker-infos-url = URL трекера
tracker-infos-version = Версия прошивки
tracker-infos-hardware_rev = Ревизия устройства
tracker-infos-hardware_identifier = ID оборудования
tracker-infos-imu = Датчик IMU
tracker-infos-board_type = Основная плата
## Tracker settings
@@ -176,7 +190,7 @@ tracker-settings-mounting_section = Положение крепления
tracker-settings-mounting_section-description = Где прикреплен трекер?
tracker-settings-mounting_section-edit = Изменить прикрепление
tracker-settings-drift_compensation_section = Разрешить компенсацию дрифта
tracker-settings-drift_compensation_section-description = Должен ли этот трекер компенсировать свой дрифт, когда включена компенсация дрифта?
tracker-settings-drift_compensation_section-description = Должен ли этот трекер компенсировать свой дрифт?
tracker-settings-drift_compensation_section-edit = Разрешить компенсацию дрифта
# The .<name> means it's an attribute and it's related to the top key.
# In this case that is the settings for the assignment section.
@@ -252,6 +266,7 @@ settings-sidebar-fk_settings = Настройки трекеров
settings-sidebar-gesture_control = Настройки жестов
settings-sidebar-interface = Интерфейс
settings-sidebar-osc_router = OSC роутер
settings-sidebar-osc_trackers = VRChat OSC Трекеры
settings-sidebar-utils = Утилиты
settings-sidebar-serial = Консоль
@@ -442,6 +457,7 @@ settings-osc-vrchat-network-address-placeholder = VRChat ip адрес
settings-osc-vrchat-network-trackers = Трекеры
settings-osc-vrchat-network-trackers-description = Переключите отправку определенных трекеров через OSC.
settings-osc-vrchat-network-trackers-chest = Грудь
settings-osc-vrchat-network-trackers-hip = Таз
settings-osc-vrchat-network-trackers-knees = Колени
settings-osc-vrchat-network-trackers-feet = Ступни
settings-osc-vrchat-network-trackers-elbows = Локти
@@ -490,6 +506,7 @@ onboarding-setup_warning =
<b>Предупреждение.</b> Для правильного отслеживания требуется первоначальная настройка,
это необходимо, если вы впервые используете SlimeVR.
onboarding-setup_warning-skip = Пропустить настройку
onboarding-setup_warning-cancel = Продолжить настройку
## Wi-Fi setup
@@ -512,7 +529,26 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Вернуться к калибровке крепления
onboarding-reset_tutorial = Сбросить туториал
onboarding-reset_tutorial-description = Эта функция не завершена, просто нажмите продолжить
onboarding-reset_tutorial-explanation = Пока вы пользуетесь своими трекерами, они могут не выровняться из-за дрейфа IMU при рыскании или из-за того, что вы, возможно, переместили их физически. У вас есть несколько способов исправить это.
onboarding-reset_tutorial-skip = Пропустить шаг
# Cares about multiline
onboarding-reset_tutorial-0 =
Коснитесь { $taps } раз выделенного трекера, чтобы активировать сброс рыскания.
Это заставит трекеры смотреть в том же направлении, что и ваш HMD.
# Cares about multiline
onboarding-reset_tutorial-1 =
Нажмите { $taps } раз выделенный трекер, чтобы запустить полный сброс.
Вы должны стоять для этого в (i-позе). Существует задержка в 3 секунды (настраиваемая), прежде чем сброс произойдет.
Это полностью сбрасывает положение и вращение всех ваших трекеров. Это должно исправить большинство проблем.
# Cares about multiline
onboarding-reset_tutorial-2 =
Нажмите { $taps } несколько раз на выделенный трекер, чтобы активировать сброс настроек.
Сброс монтажа помогает узнать, как на самом деле на вас надеты трекеры, поэтому, если вы случайно переместили их и сильно изменили их ориентацию, это поможет.
Вы должны быть в позе, как будто вы катаетесь на лыжах, как показано в мастере автоматического монтажа, и у вас есть 3-секундная задержка (настраиваемая) перед тем, как она сработает.
## Setup start
@@ -563,6 +599,27 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = Я подключил все трекеры!
## Tracker calibration tutorial
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 = Калибровка
onboarding-calibration_tutorial-status-success = Хорошо!
onboarding-calibration_tutorial-status-error = Трекер был перемещен
## Tracker assignment tutorial
onboarding-assignment_tutorial = Как подготовить Slime Трекер перед тем, как надеть его
onboarding-assignment_tutorial-first_step = 1. Наклейте стикер с частью тела (если он у вас есть) на трекер по вашему выбору.
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Стикер
onboarding-assignment_tutorial-second_step = 2. Прикрепите ремешок к вашему трекеру, придерживая лицевую сторону ремешка со стороны крючка и петли в следующем положении:
onboarding-assignment_tutorial-second_step-continuation = Сторона крючка и петли для удлинителя должна быть в этой ориентации:
onboarding-assignment_tutorial-done = Я наклеил стикеры и ремешки!
## Tracker assignment setup
onboarding-assign_trackers-back = Вернуться к вводу данных Wi-Fi
@@ -651,6 +708,17 @@ onboarding-assign_trackers-warning-WAIST =
## Tracker mounting method choose
onboarding-choose_mounting = Какой метод калибровки монтажа использовать?
# Multiline text
onboarding-choose_mounting-description = Ориентация крепления корректирует размещение трекеров на вашем теле.
onboarding-choose_mounting-auto_mounting = Автоматическая привязка
# Italized text
onboarding-choose_mounting-auto_mounting-label = Экспериментальный
onboarding-choose_mounting-auto_mounting-description = Это автоматически определит направления монтажа для всех ваших трекеров из 2 поз
onboarding-choose_mounting-manual_mounting = Ручная привязка
# Italized text
onboarding-choose_mounting-manual_mounting-label = Рекомендованный
onboarding-choose_mounting-manual_mounting-description = Это позволит вам выбрать направление монтажа вручную для каждого трекера
## Tracker manual mounting setup
@@ -683,6 +751,21 @@ onboarding-automatic_mounting-put_trackers_on-next = Я включил и над
## Tracker proportions method choose
onboarding-choose_proportions = Какой метод калибровки пропорций использовать?
# Multiline string
onboarding-choose_proportions-description =
Пропорции тела используются для определения размеров вашего тела. Они необходимы для расчета местоположения трекеров.
Если пропорции вашего тела не соответствуют сохраненным, точность отслеживания будет хуже, и вы заметите такие вещи, как катание на коньках или скольжение, или ваше тело не совсем соответствует вашему аватару.
onboarding-choose_proportions-auto_proportions = Автоматическая привязка
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Рекомендуется
onboarding-choose_proportions-auto_proportions-description = Это позволит угадать ваши пропорции, записав образец ваших движений и передав его через алгоритм.
onboarding-choose_proportions-manual_proportions = Ручные пропорции
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = Для небольших штрихов
onboarding-choose_proportions-manual_proportions-description = Это позволит вам настроить пропорции вручную, изменив их напрямую.
onboarding-choose_proportions-export = Экспорт пропорций
onboarding-choose_proportions-file_type = Файл пропорций тела
## Tracker manual proportions setup
@@ -702,12 +785,30 @@ onboarding-automatic_proportions-prev_step = Предыдущий шаг
onboarding-automatic_proportions-put_trackers_on-title = Наденьте ваши трекеры
onboarding-automatic_proportions-put_trackers_on-description = Чтобы откалибровать ваши пропорции, мы собираемся использовать трекеры, которые вы только что назначили. Включите все свои трекеры, вы можете увидеть, какие из них какие на рисунке справа.
onboarding-automatic_proportions-put_trackers_on-next = Я надел все свои трекеры
onboarding-automatic_proportions-requirements-title = Требования
# Each line of text is a different list item
onboarding-automatic_proportions-requirements-description =
У вас есть как минимум достаточно трекеров, чтобы отслеживать ваши ноги (обычно 5 трекеров).
У вас есть трекеры и гарнитура.
Вы носите трекеры и гарнитуру.
Ваши трекеры и гарнитура подключены к серверу SlimeVR.
Ваши трекеры и гарнитура правильно работают на сервере SlimeVR.
Ваша гарнитура передает данные о местоположении на сервер SlimeVR (обычно это означает, что SteamVR запущен и подключен к SlimeVR с помощью драйвера SlimeVR SteamVR).
onboarding-automatic_proportions-requirements-next = Я прочитал требования
onboarding-automatic_proportions-start_recording-title = Будьте готовы к движению
onboarding-automatic_proportions-start_recording-description = Теперь мы собираемся записать некоторые конкретные позы и движения. Они будут запрошены на следующем экране. Будьте готовы начать, когда кнопка будет нажата!
onboarding-automatic_proportions-start_recording-next = Начать запись
onboarding-automatic_proportions-recording-title = Запись
onboarding-automatic_proportions-recording-description-p0 = Запись в процессе...
onboarding-automatic_proportions-recording-description-p1 = Сделайте эти движения:
# Each line of text is a different list item
onboarding-automatic_proportions-recording-steps =
Стоя прямо, покрутите головой по кругу.
Наклоните спину вперед и присядьте на корточки. Сидя на корточках, посмотрите налево, затем направо.
Поверните верхнюю часть туловища влево (против часовой стрелки), затем наклонитесь к земле.
Поверните верхнюю часть туловища вправо (по часовой стрелке), затем наклонитесь к земле.
Вращайте бедрами круговыми движениями, как будто вы используете хула-хуп.
Если на запись осталось время, вы можете повторять эти действия до тех пор, пока она не будет завершена.
onboarding-automatic_proportions-recording-processing = Обработка результата...
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =
@@ -729,3 +830,13 @@ onboarding-automatic_proportions-done-description = Калибровка про
## Home
home-no_trackers = Трекеры не обнаружены и не привязаны
## Status system
status_system-StatusTrackerReset = Рекомендуется выполнить полный сброс, так как один или несколько трекеров не настроены.
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] В настоящее время не подключен к приложению SlimeVR Feeder.
*[other] В настоящее время не подключен к SteamVR через драйвер SlimeVR.
}
status_system-StatusTrackerError = В трекере { $trackerName } обнаружена ошибка.

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -11,29 +8,69 @@
## Websocket (server) status
websocket-connecting = กำลังเชื่อมต่อกับเซิร์ฟเวอร์
websocket-connection_lost = ขาดการเชื่อมต่อกับเซิร์ฟเวอร์ กำลังลองเชื่อมใหม่
## Update notification
version_update-title = มีเวอใหม่พร้อมแล้ว: { $version }
version_update-update = อัพเดท
version_update-close = ปิด
## Tips
tips-do_not_move_heels = ให้แน่ใจว่าเท้าไม่ขยับระหว่างการอัด/บันทึก
## Body parts
body_part-HEAD = หัว
body_part-NECK = คอ
body_part-RIGHT_SHOULDER = ใหล่ขวา
body_part-RIGHT_UPPER_ARM = แขนขวาส่วนบน
body_part-RIGHT_LOWER_ARM = แขนขวาส่วนล่าง
body_part-RIGHT_HAND = มือขวา
body_part-RIGHT_UPPER_LEG = น่องขาขวา
body_part-RIGHT_LOWER_LEG = ข้อเท้าขวา
body_part-RIGHT_FOOT = เท้าขวา
body_part-CHEST = หน้าอก
body_part-WAIST = เอว
body_part-HIP = สะโพก
body_part-LEFT_SHOULDER = ใหล่ซ้าย
body_part-LEFT_UPPER_ARM = แขนซ้ายส่วนบน
body_part-LEFT_LOWER_ARM = แขนซ้ายส่วนล่าง
body_part-LEFT_HAND = มือซ้าย
body_part-LEFT_UPPER_LEG = น่องขาซ้าย
body_part-LEFT_LOWER_LEG = ข้อเท้าซ้าย
body_part-LEFT_FOOT = เท้าขวา
## Proportions
skeleton_bone-NONE = ไม่มี
skeleton_bone-NECK = ความยาวขอ
skeleton_bone-UPPER_ARM = ความยาวแขนส่วนบน
skeleton_bone-LOWER_ARM = ความยาวแขนส่วนล่าง
## Tracker reset buttons
reset-reset_all = รีเซ็ตสัดส่วนร้างกายทั้งหมด
reset-full = รีเซ็ตทั้งหมด
## Serial detection stuff
serial_detection-open_wifi = เชื่อมต่อ Wi-Fi
serial_detection-close = ปิด
## Navigation bar
navbar-home = หน้าหลัก
navbar-body_proportions = สัดส่วนร่างกาย
navbar-onboarding = Setup Wizard
navbar-settings = ตั้งค่า
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-recording = กำลังอัดบันทึก
## Tracking pause
## Widget: Overlay settings
@@ -44,45 +81,76 @@ websocket-connecting = กำลังเชื่อมต่อกับเซ
## Widget: Developer settings
widget-developer_mode = โหมดนักพัฒนา
widget-developer_mode-sort_by_name = เรียงด้วยชื่อ
widget-developer_mode-more_info = ข้อมูลเพิ่มเติม
## Widget: IMU Visualizer
widget-imu_visualizer = การหมุน
widget-imu_visualizer-rotation_preview = ดูตัวอย่าง
widget-imu_visualizer-rotation_hide = ซ่อน
## Tracker status
tracker-status-none = ไม่มีสถานะ
tracker-status-busy = กังลังทำงาน
tracker-status-error = ข้อผิดผลาด
tracker-status-disconnected = หลุดการเชื่อมต่อ
tracker-status-ok = OK
## Tracker status columns
tracker-table-column-name = ชื่อ
tracker-table-column-type = พิมพ์
tracker-table-column-battery = แบตเตอรี่
tracker-table-column-ping = ความหน่วง
tracker-table-column-temperature = อุณหภูมิ °C
tracker-table-column-url = URL
## Tracker rotation
tracker-rotation-front = หน้า
tracker-rotation-left = ซ้าย
tracker-rotation-right = ขวา
tracker-rotation-back = หลัง
## Tracker information
tracker-infos-manufacturer = ผู้ผลิต
tracker-infos-version = เวอร์ชั่นของเฟิร์มแวร์
tracker-infos-board_type = เมนบอร์ด
## Tracker settings
tracker-settings-assignment_section = กำหนด
## Tracker part card info
tracker-part_card-no_name = ไม่มีชื่อ
## Body assignment menu
## Tracker assignment menu
tracker_selection_menu-neck_warning-done = ฉันเข้าใจในความเสี่ยง
tracker_selection_menu-neck_warning-cancel = ยกเลิก
## Mounting menu
mounting_selection_menu-close = ปิด
## Sidebar settings
settings-sidebar-title = การตั้งค่า
## SteamVR settings
## Tracker mechanics
settings-general-tracker_mechanics-filtering-amount = จำนวน
## FK/Tracking settings
@@ -92,42 +160,85 @@ websocket-connecting = กำลังเชื่อมต่อกับเซ
## Interface settings
settings-general-interface-dev_mode = โหมดนักพัฒนา
settings-general-interface-dev_mode-label = โหมดนักพัฒนา
settings-general-interface-theme = สีธีม
settings-general-interface-lang = เลือกภาษา
settings-general-interface-lang-description = เลือกภาษาตั้งต้นที่คุณต้องการใช้
settings-general-interface-lang-placeholder = เลือกภาษาที่ใช้
## Serial settings
settings-serial-reboot = เริ่มการทำงานใหม่
settings-serial-factory_reset = รีเซ็ตเป็นค่าจากโรงงาน
settings-serial-factory_reset-warning-ok = ฉันรู้ว่าฉันกําลังทําอะไรอยู่
settings-serial-factory_reset-warning-cancel = ยกเลิก
settings-serial-auto_dropdown_item = อัตโนมัติ
## OSC router settings
settings-osc-router-enable = เปิดใช้งาน
settings-osc-router-enable-label = เปิดใช้งาน
settings-osc-router-network = พอร์ตเครือข่าย
## OSC VRChat settings
settings-osc-vrchat-enable = เปิดใช้งาน
settings-osc-vrchat-enable-label = เปิดใช้งาน
settings-osc-vrchat-network-trackers-chest = หน้าอก
settings-osc-vrchat-network-trackers-hip = สะโพก
settings-osc-vrchat-network-trackers-knees = หัวเข่า
settings-osc-vrchat-network-trackers-feet = เท้า
settings-osc-vrchat-network-trackers-elbows = ข้อศอก
## VMC OSC settings
settings-osc-vmc-enable = เปิดใช้งาน
settings-osc-vmc-enable-label = เปิดใช้งาน
## Setup/onboarding menu
onboarding-skip = ข้ามการตั้งค่า
onboarding-continue = ดำเนินการต่อ
onboarding-previous_step = ขั้นตอนก่อนหน้า
onboarding-setup_warning-skip = ข้ามการตั้งค่า
## Wi-Fi setup
onboarding-wifi_creds-submit = ส่ง
onboarding-wifi_creds-ssid =
.label = ชื่อ Wi-Fi
.placeholder = ใส่ชื่อ Wi-Fi
onboarding-wifi_creds-password =
.label = รหัสผ่าน
.placeholder = ใส่รหัสผ่าน
## Mounting setup
## Setup start
onboarding-home = ยินดีต้อนรับสู่ SlimeVR
## Enter VR part of setup
onboarding-enter_vr-ready = ฉันพร้อมแล้ว
## Setup done
onboarding-done-title = คุณพร้อมแล้ว!
## Tracker connection setup
onboarding-connect_tracker-connection_status-done = เชื่อมต่อกับเซิร์ฟเวอร์แล้ว
## Tracker calibration tutorial
onboarding-calibration_tutorial-calibrate = ฉันได้วาง tracker บนโต๊ะแล้ว
onboarding-calibration_tutorial-status-success = เยี่ยม!
## Tracker assignment tutorial
## Tracker assignment setup
@@ -140,18 +251,39 @@ websocket-connecting = กำลังเชื่อมต่อกับเซ
## Tracker manual mounting setup
onboarding-manual_mounting-next = ขั้นตอนถัดไป
## Tracker automatic mounting setup
onboarding-automatic_mounting-next = ขั้นตอนถัดไป
onboarding-automatic_mounting-prev_step = ขั้นตอนก่อนหน้า
onboarding-automatic_mounting-done-restart = ลองอีกครั้ง
onboarding-automatic_mounting-preparation-title = จัดเตรียมพร้อม
## Tracker proportions method choose
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = แนะนำ
## Tracker manual proportions setup
onboarding-manual_proportions-precision = ปรับด้วยความแม่นยํา
## Tracker automatic proportions setup
onboarding-automatic_proportions-title = วัดสัดส่วนร่างกายของคุณ
onboarding-automatic_proportions-requirements-title = ต้องการ
onboarding-automatic_proportions-requirements-next = ฉันได้อ่านสิ่งที่ต้องการแล้ว
onboarding-automatic_proportions-start_recording-next = เริ่มการบันทึก
onboarding-automatic_proportions-recording-title = REC
onboarding-automatic_proportions-recording-description-p0 = กําลังบันทึก...
onboarding-automatic_proportions-recording-description-p1 = ทําการเคลื่อนไหวที่แสดงด้านล่าง:
onboarding-automatic_proportions-recording-processing = กำลังประมวลผลผลลัพธ์
onboarding-automatic_proportions-verify_results-title = ยืนยันผลลัพธ์
onboarding-automatic_proportions-verify_results-description = ตรวจสอบผลลัพธ์ด้านล่างว่าดูถูกต้องหรือไม่?
## Home
## Status system

View File

@@ -1,6 +1,3 @@
### SlimeVR complete GUI translations
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
@@ -13,6 +10,12 @@
websocket-connecting = Sunucuya bağlanılıyor
websocket-connection_lost = Sunucuyla bağlantı kesildi. Tekrar bağlanılmaya çalışılıyor...
## Update notification
version_update-title = Yeni sürüm mevcut: { $version }
version_update-update = Güncelle
version_update-close = Kapat
## Tips
tips-find_tracker = Hangi takipçi hangisi emin değil misin? Takipçilerden birini hareket ettirerek belirleyebilirsin.
@@ -30,7 +33,7 @@ body_part-RIGHT_HAND = Sağ el
body_part-RIGHT_UPPER_LEG = Sağ uyluk
body_part-RIGHT_LOWER_LEG = Sağ ayak bileği
body_part-RIGHT_FOOT = Sağ ayak
body_part-RIGHT_CONTROLLER = Sağ oyun kolu
body_part-UPPER_CHEST = Üst göğüs
body_part-CHEST = Göğüs
body_part-WAIST = Bel
body_part-HIP = Kalça
@@ -41,19 +44,21 @@ body_part-LEFT_HAND = Sol el
body_part-LEFT_UPPER_LEG = Sol uyluk
body_part-LEFT_LOWER_LEG = Sol ayak bileği
body_part-LEFT_FOOT = Sol ayak
body_part-LEFT_CONTROLLER = Sol oyun kolu
## Proportions
skeleton_bone-NONE = Yok
skeleton_bone-HEAD = Kafa hizası
skeleton_bone-NECK = Boyun Uzunluğu
skeleton_bone-CHEST = Göğüs Uzunluğu
skeleton_bone-torso_group = Gövde uzunluğu
skeleton_bone-UPPER_CHEST = Üst Göğüs Uzunluğu
skeleton_bone-CHEST_OFFSET = Göğüs hizası
skeleton_bone-CHEST = Göğüs Uzunluğu
skeleton_bone-WAIST = Bel Uzunluğu
skeleton_bone-HIP = Kalça Uzunluğu
skeleton_bone-HIP_OFFSET = Kalça hizası
skeleton_bone-HIPS_WIDTH = Kalça Genişliği
skeleton_bone-leg_group = Bacak uzunluğu
skeleton_bone-UPPER_LEG = Üst Bacak Uzunluğu
skeleton_bone-LOWER_LEG = Alt Bacak Uzunluğu
skeleton_bone-FOOT_LENGTH = Ayak Uzunluğu
@@ -61,32 +66,41 @@ skeleton_bone-FOOT_SHIFT = Ayak hizası
skeleton_bone-SKELETON_OFFSET = İskelet hizası
skeleton_bone-SHOULDERS_DISTANCE = Omuz Mesafesi
skeleton_bone-SHOULDERS_WIDTH = Omuz Genişliği
skeleton_bone-arm_group = Kol uzunluğu
skeleton_bone-UPPER_ARM = Üst Kol Uzunluğu
skeleton_bone-LOWER_ARM = Alt Kol Uzunluğu
skeleton_bone-CONTROLLER_Y = Oyun kolu uzaklığı Y
skeleton_bone-CONTROLLER_Z = Oyun kolu uzaklığı Z
skeleton_bone-ELBOW_OFFSET = Dirsek hizası
## Tracker reset buttons
reset-reset_all = Tüm oranları sıfırla
reset-full = Sıfırlama
reset-quick = Hızlı Sıfırlama
## Serial detection stuff
serial_detection-new_device-p0 = Yeni seri cihaz algılandı!
serial_detection-new_device-p1 = Wi-Fi bilgilerinizi girin!
serial_detection-new_device-p2 = Lütfen onunla ne yapmak istediğinizi seçin
serial_detection-open_wifi = Wi-Fi'ye bağlan
serial_detection-open_serial = Seri Konsolu Aç
serial_detection-submit = Gönder!
serial_detection-close = Kapat
## Navigation bar
navbar-home = Ana Menü
navbar-body_proportions = Vücut Oranları
navbar-onboarding = Kurulum Sihirbazı
navbar-settings = Ayarlar
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = BVH Kaydet
bvh-recording = Kaydediliyor
## Tracking pause
tracking-unpaused = Takibi duraklat
## Widget: Overlay settings
@@ -96,15 +110,36 @@ navbar-settings = Ayarlar
## Widget: Developer settings
widget-developer_mode = Geliştirici Modu
widget-developer_mode-high_contrast = Yüksek kontrast
widget-developer_mode-precise_rotation = Hassas dönüş
widget-developer_mode-sort_by_name = Ada göre sırala
widget-developer_mode-more_info = Daha fazla bilgi
## Widget: IMU Visualizer
widget-imu_visualizer = Rotasyon
widget-imu_visualizer-rotation_preview = Önizle
widget-imu_visualizer-rotation_hide = Gizle
## Tracker status
tracker-status-none = Durum Yok
tracker-status-busy = Meşgul
tracker-status-error = Hata
tracker-status-disconnected = Bağlantı kesildi
tracker-status-ok = İYİ
## Tracker status columns
tracker-table-column-name = İsim
tracker-table-column-type = Tür
tracker-table-column-battery = Pil
tracker-table-column-tps = TPS
tracker-table-column-temperature = Sıcaklık °C
tracker-table-column-rotation = Rotasyon X/Y/Z
tracker-table-column-position = Pozisyon X/Y/Z
tracker-table-column-url = URL
## Tracker rotation
@@ -118,34 +153,95 @@ tracker-rotation-back = Arka
tracker-infos-manufacturer = Üretici
tracker-infos-display_name = Görünen Ad
tracker-infos-custom_name = Özel Ad
tracker-infos-url = Takipçi URL'si
tracker-infos-version = Yazılım Sürümü
tracker-infos-hardware_rev = Donanım Revizyonu
tracker-infos-hardware_identifier = Donanım Kimliği
tracker-infos-imu = IMU Sensör
tracker-infos-board_type = Ana kart
## Tracker settings
tracker-settings-back = Takipçi listesine geri dön
tracker-settings-title = Takipçi ayarları
tracker-settings-assignment_section-description = Tracker'in vücudun hangi kısmına atandığı.
# The .<name> means it's an attribute and it's related to the top key.
# In this case that is the settings for the assignment section.
tracker-settings-name_section = Takipçi adı
tracker-settings-name_section-placeholder = NightyBeast'in sol bacağı
## Tracker part card info
tracker-part_card-no_name = İsimsiz
tracker-part_card-unassigned = Atanmamış
## Body assignment menu
body_assignment_menu = Bu takipçinin nerede olmasını istiyorsunuz?
body_assignment_menu-manage_trackers = Tüm takipçileri yönet
## Tracker assignment menu
# A -translation_key (with a dash in the front) means that it's a label.
# It can only be used in the translation file, it's nice for reusing names and that kind of stuff.
#
# We are using it here because english doesn't require changing the text in each case but
# maybe your language does.
-tracker_selection-part = hangi takipçiyi atayacaksınız?
tracker_selection_menu-HEAD = Başınıza { -tracker_selection-part }
tracker_selection_menu-RIGHT_SHOULDER = Sağ omuzunuza { -tracker_selection-part }
tracker_selection_menu-RIGHT_UPPER_ARM = Sağ üst kolunuza { -tracker_selection-part }
tracker_selection_menu-RIGHT_LOWER_ARM = Sağ alt kolunuza { -tracker_selection-part }
tracker_selection_menu-RIGHT_HAND = Sağ elinize { -tracker_selection-part }
tracker_selection_menu-RIGHT_UPPER_LEG = Say kalçanıza { -tracker_selection-part }
tracker_selection_menu-RIGHT_LOWER_LEG = Sağ ayak bileğinize { -tracker_selection-part }
tracker_selection_menu-RIGHT_FOOT = Sağ ayağınıza { -tracker_selection-part }
tracker_selection_menu-UPPER_CHEST = Üst göğüsünüze { -tracker_selection-part }
tracker_selection_menu-unassigned = Atanmamış takipçiler
tracker_selection_menu-assigned = Atanan takipçiler
tracker_selection_menu-neck_warning-done = Riskleri anlıyorum
tracker_selection_menu-neck_warning-cancel = İptal
## Mounting menu
mounting_selection_menu = Bu takipçinin nerede olmasını istiyorsunuz?
mounting_selection_menu-close = Kapat
## Sidebar settings
settings-sidebar-title = Ayarlar
settings-sidebar-general = Genel
settings-sidebar-interface = Arayüz
settings-sidebar-osc_router = OSC yönlendirici
settings-sidebar-osc_trackers = VRChat OSC Takipçileri
settings-sidebar-serial = Seri konsol
## SteamVR settings
settings-general-steamvr = SteamVR
settings-general-steamvr-subtitle = SteamVR takipçileri
settings-general-steamvr-trackers-waist = Bel
settings-general-steamvr-trackers-chest = Göğüs
settings-general-steamvr-trackers-feet = Ayaklar
settings-general-steamvr-trackers-knees = Dizler
settings-general-steamvr-trackers-elbows = Dirsekler
settings-general-steamvr-trackers-hands = Eller
## Tracker mechanics
settings-general-tracker_mechanics-filtering-amount = Miktar
## FK/Tracking settings
settings-general-fk_settings-leg_fk = Bacak takibi
settings-general-fk_settings-arm_fk = Kol takibi
settings-general-fk_settings-skeleton_settings = İskelet ayarları
settings-general-fk_settings-skeleton_settings-description = İskelet ayarlarınıın veya kapatın. Bunlarıık bırakmanız önerilir.
settings-general-fk_settings-skeleton_settings-extended_spine = Uzatılmış omurga
settings-general-fk_settings-skeleton_settings-extended_pelvis = Uzatılmış pelvis
settings-general-fk_settings-skeleton_settings-extended_knees = Uzatılmış diz
settings-general-fk_settings-vive_emulation-title = Vive emülasyonu
settings-general-fk_settings-vive_emulation-label = Vive emülasyonunu etkinleştir
## Gesture control settings (tracker tapping)
@@ -172,6 +268,9 @@ settings-osc-vrchat-enable = Etkinleştir
settings-osc-vrchat-enable-label = Etkinleştir
settings-osc-vrchat-network-address = Ağ adresi
## VMC OSC settings
## Setup/onboarding menu
@@ -193,15 +292,30 @@ settings-osc-vrchat-network-address = Ağ adresi
## Tracker connection setup
## Tracker calibration tutorial
## Tracker assignment tutorial
## Tracker assignment setup
## Tracker assignment warnings
## Tracker mounting method choose
## Tracker manual mounting setup
## Tracker automatic mounting setup
## Tracker proportions method choose
## Tracker manual proportions setup
@@ -210,3 +324,6 @@ settings-osc-vrchat-network-address = Ağ adresi
## Home
## Status system

View File

@@ -0,0 +1,718 @@
# Please developers (not translators) don't reuse a key inside another key
# or concat text with a translation string in the code, use the appropriate
# features like variables and selectors in each appropriate case!
# And also comment the string if it's something not easy to translate, so you help
# translators on what it means
## Websocket (server) status
websocket-connecting = Підключення до сервера
websocket-connection_lost = З'єднання з сервером втрачено. Повторне підключення...
## Update notification
version_update-title = Доступна нова версія: { $version }
version_update-description = Натискання "{ version_update-update }" почнеться завантаження SlimeVR installer.
version_update-update = Оновлення
version_update-close = Закрити
## Tips
tips-find_tracker = Не знаєте який трекер вибирати? Потрясіть трекер і він підсвітить відповідний пункт.
tips-do_not_move_heels = Переконайтеся, що не рухаєте п'ятами під час запису!
tips-file_select = Перетягніть файли для використання або <u>знайдіть</u>.
tips-tap_setup = Ви можете повільно постукати 2 рази по трекеру, щоб вибрати його, замість того, щоб вибирати його з меню.
## Body parts
body_part-NONE = Не призначено
body_part-HEAD = Голова
body_part-NECK = Шия
body_part-RIGHT_SHOULDER = Праве плече
body_part-RIGHT_UPPER_ARM = Права верхня частина руки
body_part-RIGHT_LOWER_ARM = Права нижня частина руки
body_part-RIGHT_HAND = Права рука
body_part-RIGHT_UPPER_LEG = Праве стегно
body_part-RIGHT_LOWER_LEG = Права щиколотка
body_part-RIGHT_FOOT = Права нога
body_part-UPPER_CHEST = Верхня частина грудей
body_part-CHEST = Груди
body_part-WAIST = Талія
body_part-HIP = Стегно
body_part-LEFT_SHOULDER = Ліве плече
body_part-LEFT_UPPER_ARM = Ліва верхня частина руки
body_part-LEFT_LOWER_ARM = Ліва нижня частина руки
body_part-LEFT_HAND = Ліва рука
body_part-LEFT_UPPER_LEG = Ліве стегно
body_part-LEFT_LOWER_LEG = Ліва щиколотка
body_part-LEFT_FOOT = Ліва нога
## Proportions
skeleton_bone-NONE = Нічого
skeleton_bone-HEAD = Зсув голови
skeleton_bone-NECK = Довжина шиї
skeleton_bone-torso_group = Довжина тулуба
skeleton_bone-UPPER_CHEST = Довжина верхньої частини грудей
skeleton_bone-CHEST_OFFSET = Зміщення грудної клітини
skeleton_bone-CHEST = Довжина грудей
skeleton_bone-WAIST = Довжина талії
skeleton_bone-HIP = Довжина стегна
skeleton_bone-HIP_OFFSET = Зміщення стегна
skeleton_bone-HIPS_WIDTH = Ширина стегон
skeleton_bone-leg_group = Довжина ніг
skeleton_bone-UPPER_LEG = Довжина верхньої частини ноги
skeleton_bone-LOWER_LEG = Довжина гомілки
skeleton_bone-FOOT_LENGTH = Довжина стопи
skeleton_bone-FOOT_SHIFT = Зміщення стопи
skeleton_bone-SKELETON_OFFSET = Зміщення скелета
skeleton_bone-SHOULDERS_DISTANCE = Відстань між плечима
skeleton_bone-SHOULDERS_WIDTH = Ширина плечей
skeleton_bone-arm_group = Довжина руки
skeleton_bone-UPPER_ARM = Довжина верхньої частини руки
skeleton_bone-LOWER_ARM = Довжина нижньої частини руки
skeleton_bone-HAND_Y = Відстань рук Y
skeleton_bone-HAND_Z = Відстань руки Z
skeleton_bone-ELBOW_OFFSET = Зміщення ліктя
## Tracker reset buttons
reset-reset_all = Скинути всі пропорції
reset-full = Повне скидання
reset-mounting = Скинути закріплення
reset-yaw = Скинути нахил
## Serial detection stuff
serial_detection-new_device-p0 = Виявлено новий послідовний пристрій!
serial_detection-new_device-p1 = Введіть дані вашого Wi-Fi!
serial_detection-new_device-p2 = Будь ласка, виберіть, що ви хочете з ним зробити
serial_detection-open_wifi = Підключити до Wi-Fi
serial_detection-open_serial = Відкрити послідовну консоль
serial_detection-submit = Підтвердити!
serial_detection-close = Закрити
## Navigation bar
navbar-home = Домашня сторінка
navbar-body_proportions = Пропорції тіла
navbar-trackers_assign = Призначення трекера
navbar-mounting = Калібрування закріплення
navbar-onboarding = Майстер налаштування
navbar-settings = Параметри
## Biovision hierarchy recording
bvh-start_recording = Запис BVH
bvh-recording = Запис...
## Tracking pause
tracking-unpaused = Призупинити трекінг
tracking-paused = Продовжити трекінг
## Widget: Overlay settings
widget-overlay = Накладання
widget-overlay-is_visible_label = Показати накладання у SteamVR
widget-overlay-is_mirrored_label = Відображення накладання як дзеркала
## Widget: Drift compensation
widget-drift_compensation-clear = Очистити компенсацію дрейфу
## Widget: Developer settings
widget-developer_mode = Режим розробника
widget-developer_mode-high_contrast = Висока контрастність
widget-developer_mode-precise_rotation = Точне обертання
widget-developer_mode-fast_data_feed = Швидка подача даних
widget-developer_mode-filter_slimes_and_hmd = Фільтрація слаймів і шолому
widget-developer_mode-sort_by_name = Сортування за назвою
widget-developer_mode-raw_slime_rotation = Необроблене обертання
widget-developer_mode-more_info = Детальніше
## Widget: IMU Visualizer
widget-imu_visualizer = Обертання
widget-imu_visualizer-rotation_raw = Необроблене
widget-imu_visualizer-rotation_preview = Попередній перегляд
widget-imu_visualizer-rotation_hide = Приховати
## Tracker status
tracker-status-none = Немає статусу
tracker-status-busy = Зайнятий
tracker-status-error = Помилка
tracker-status-disconnected = Відключено
tracker-status-occluded = Закрито
tracker-status-ok = OK
## Tracker status columns
tracker-table-column-name = Ім'я
tracker-table-column-type = Тип
tracker-table-column-battery = Батарея
tracker-table-column-ping = Пінг
tracker-table-column-tps = TPS
tracker-table-column-temperature = Темп. °C
tracker-table-column-linear-acceleration = Прискорення X/Y/Z
tracker-table-column-rotation = Обертання X/Y/Z
tracker-table-column-position = Позиція X/Y/Z
tracker-table-column-url = URL
## Tracker rotation
tracker-rotation-front = Спереду
tracker-rotation-left = Зліва
tracker-rotation-right = Справа
tracker-rotation-back = Ззаду
## Tracker information
tracker-infos-manufacturer = Виробник
tracker-infos-display_name = Відображуване ім'я
tracker-infos-custom_name = Персональне ім'я
tracker-infos-url = URL трекера
tracker-infos-version = Версія прошивки
tracker-infos-hardware_rev = Ревізія обладнання
tracker-infos-hardware_identifier = Ідентифікатор обладнання
tracker-infos-imu = IMU Сенсор
tracker-infos-board_type = Основна плата
## Tracker settings
tracker-settings-back = Повернутися до списку трекерів
tracker-settings-title = Налаштування трекеру
tracker-settings-assignment_section = Призначення
tracker-settings-assignment_section-description = До якої частини тіла призначенний трекер.
tracker-settings-assignment_section-edit = Редагування призначення
tracker-settings-mounting_section = Позиція закріпу
tracker-settings-mounting_section-description = Де закріплено трекер?
tracker-settings-mounting_section-edit = Редагувати закріплення
tracker-settings-drift_compensation_section = Дозволити компенсацію дрейфу
tracker-settings-drift_compensation_section-description = Чи повинен цей трекер компенсувати свій дрейф, коли включена компенсація дрейфу?
tracker-settings-drift_compensation_section-edit = Дозволити компенсацію дрейфу
# The .<name> means it's an attribute and it's related to the top key.
# In this case that is the settings for the assignment section.
tracker-settings-name_section = Ім'я трекера
tracker-settings-name_section-description = Дайте йому миле прізвисько °^°
tracker-settings-name_section-placeholder = Ліва нога NightyBeast
## Tracker part card info
tracker-part_card-no_name = Немає імені
tracker-part_card-unassigned = Непризначений
## Body assignment menu
body_assignment_menu = Де ви хочете, щоб був цей трекер?
body_assignment_menu-description = Виберіть місце, куди потрібно призначити цей трекер. Крім того, ви можете керувати всіма трекерами одночасно, а не по одному.
body_assignment_menu-show_advanced_locations = Відображення розширених точок розташувань
body_assignment_menu-manage_trackers = Керування всіма трекерами
body_assignment_menu-unassign_tracker = Відв'язати трекер
## Tracker assignment menu
# A -translation_key (with a dash in the front) means that it's a label.
# It can only be used in the translation file, it's nice for reusing names and that kind of stuff.
#
# We are using it here because english doesn't require changing the text in each case but
# maybe your language does.
-tracker_selection-part = Який трекер призначити к
tracker_selection_menu-NONE = Який трекер ви хочете відв'язати?
tracker_selection_menu-HEAD = { -tracker_selection-part } голові?
tracker_selection_menu-NECK = { -tracker_selection-part } шиї?
tracker_selection_menu-RIGHT_SHOULDER = { -tracker_selection-part } правому плечу?
tracker_selection_menu-RIGHT_UPPER_ARM = { -tracker_selection-part } правій верхній частині руці?
tracker_selection_menu-RIGHT_LOWER_ARM = { -tracker_selection-part } правій нижній частині руці?
tracker_selection_menu-RIGHT_HAND = { -tracker_selection-part } правій руці?
tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } правому стегну?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } правій щиколотці?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } правій ступні?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } правому контролеру?
tracker_selection_menu-UPPER_CHEST = { -tracker_selection-part } верхня частина грудей?
tracker_selection_menu-CHEST = { -tracker_selection-part } грудям?
tracker_selection_menu-WAIST = { -tracker_selection-part } талії?
tracker_selection_menu-HIP = { -tracker_selection-part } стегну?
tracker_selection_menu-LEFT_SHOULDER = { -tracker_selection-part } Лівому плечу?
tracker_selection_menu-LEFT_UPPER_ARM = { -tracker_selection-part } лівій верхній частині руки?
tracker_selection_menu-LEFT_LOWER_ARM = { -tracker_selection-part } лівій нижній частині руці?
tracker_selection_menu-LEFT_HAND = { -tracker_selection-part } лівій руці?
tracker_selection_menu-LEFT_UPPER_LEG = { -tracker_selection-part } лівому стегну?
tracker_selection_menu-LEFT_LOWER_LEG = { -tracker_selection-part } лівій щиколотці
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } лівій ступні?
tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part } лівому контролеру?
tracker_selection_menu-unassigned = Непризначені трекери
tracker_selection_menu-assigned = Призначені трекери
tracker_selection_menu-dont_assign = Відв'язати
# This line cares about multilines.
# <b>text</b> means that the text should be bold.
tracker_selection_menu-neck_warning =
<b>Попередження:</b> Трекер шиї може бути смертельно небезпечним, якщо його регулювати занадто щільно,
Ремінь може скоротити кровообіг до вашої голови!
tracker_selection_menu-neck_warning-done = Я розумію ризики
tracker_selection_menu-neck_warning-cancel = Скасувати
## Mounting menu
mounting_selection_menu = Де ви хочете, щоб був цей трекер?
mounting_selection_menu-close = Закрити
## Sidebar settings
settings-sidebar-title = Параметри
settings-sidebar-general = Загальні
settings-sidebar-tracker_mechanics = Механіки трекера
settings-sidebar-fk_settings = Налаштування відстеження
settings-sidebar-gesture_control = Управління жестами
settings-sidebar-interface = Інтерфейс
settings-sidebar-osc_router = OSC роутер
settings-sidebar-osc_trackers = VRChat OSC трекери
settings-sidebar-utils = Утиліти
settings-sidebar-serial = Послідовна консоль
## SteamVR settings
settings-general-steamvr = SteamVR
settings-general-steamvr-subtitle = SteamVR трекери
# Not all translation keys support multiline, only the ones that specify it will actually
# split it in lines (that also means you can split in lines however you want in those).
# The first spaces (not tabs) for indentation will be ignored, just to make the file look nice when writing.
# This one is one of this cases that cares about multilines
settings-general-steamvr-description =
Увімкніть або вимкніть певні SteamVR трекери.
Корисно для ігор або програм, які підтримують лише певні трекери.
settings-general-steamvr-trackers-waist = Талія
settings-general-steamvr-trackers-chest = Груди
settings-general-steamvr-trackers-feet = Ступні
settings-general-steamvr-trackers-knees = Коліна
settings-general-steamvr-trackers-elbows = Лікті
settings-general-steamvr-trackers-hands = Руки
## Tracker mechanics
settings-general-tracker_mechanics = Механіки трекера
settings-general-tracker_mechanics-filtering = Фільтрація
# This also cares about multilines
settings-general-tracker_mechanics-filtering-description =
Виберіть тип фільтрації для своїх трекерів.
Передбачення передбачає рух, а згладжування згладжує рух.
settings-general-tracker_mechanics-filtering-type = Тип фільтрації
settings-general-tracker_mechanics-filtering-type-none = Без фільтрації
settings-general-tracker_mechanics-filtering-type-none-description = Використовуйте обертання як є. Ніякої фільтрації не зробить.
settings-general-tracker_mechanics-filtering-type-smoothing = Згладжування
settings-general-tracker_mechanics-filtering-type-smoothing-description = Згладжує рухи, але додає деяку затримку.
settings-general-tracker_mechanics-filtering-type-prediction = Передбачення
settings-general-tracker_mechanics-filtering-type-prediction-description = Зменшує затримку і робить рухи більш швидкими, але може посилити тремтіння.
settings-general-tracker_mechanics-filtering-amount = Кількість
settings-general-tracker_mechanics-drift_compensation = Компенсація дрейфу
# This cares about multilines
settings-general-tracker_mechanics-drift_compensation-description =
Компенсує дрейф нахилу IMU, застосовуючи зворотне обертання.
Змініть суму компенсації та до того, скільки скидань враховано.
settings-general-tracker_mechanics-drift_compensation-enabled-label = Компенсація дрейфу
settings-general-tracker_mechanics-drift_compensation-amount-label = Сума компенсації
settings-general-tracker_mechanics-drift_compensation-max_resets-label = Використання до x останніх скидань
## FK/Tracking settings
settings-general-fk_settings = Налаштування відстеження
# Floor clip:
# why the name - came from the idea of noclip in video games, but is the opposite where clipping to the floor is a desired feature
# definition - Prevents the foot trackers from going lower than they where when a reset was performed
settings-general-fk_settings-leg_tweak-floor_clip = Прив'язка до підлоги
# Skating correction:
# why the name - without this enabled the feet will often slide across the ground as if your skating across the ground,
# since this largely prevents this it corrects for it hence skating correction (note this may be renamed to sliding correction)
# definition - Guesses when each foot is in contact with the ground and uses that information to improve tracking
settings-general-fk_settings-leg_tweak-skating_correction = корекція ковзання
settings-general-fk_settings-leg_tweak-toe_snap = корекція пальців ноги
settings-general-fk_settings-leg_tweak-foot_plant = корекція ступні
settings-general-fk_settings-leg_tweak-skating_correction-amount = Сила корекції ковзання
settings-general-fk_settings-leg_tweak-skating_correction-description = Корекція ковзання коригує катання на ковзанах, але може знизити точність певних моделей руху. Увімкнувши це, обов'язково повністю скиньте та відкалібруйте у грі.
settings-general-fk_settings-leg_tweak-floor_clip-description = Прив'язка до підлоги може зменшити або навіть прибрати проходження через підлогу. Коли вмикаєте, обов'язково зробіть повне скидання і перекалібровку у грі
settings-general-fk_settings-leg_tweak-toe_snap-description = Корекція пальців ноги намагається вгадати обертання ваших ступень, якщо трекери для них не використовуються
settings-general-fk_settings-leg_tweak-foot_plant-description = Корекція ступні повертає ваші ступні так, щоб вони були паралельні землі при контакті
settings-general-fk_settings-leg_fk = Трекінг ноги
settings-general-fk_settings-arm_fk = Трекінг руки
settings-general-fk_settings-arm_fk-description = Намагатися відстежувати руки за допомогою шолома, навіть якщо є інформація о позиції руки
settings-general-fk_settings-arm_fk-force_arms = Відстеження рук з шолома
settings-general-fk_settings-skeleton_settings = Налаштування скелета
settings-general-fk_settings-skeleton_settings-description = Увімкніть або вимкніть налаштування скелета. Рекомендується залишити їх увімкненими.
settings-general-fk_settings-skeleton_settings-extended_spine = Подовжений хребет
settings-general-fk_settings-skeleton_settings-extended_pelvis = Розширений таз
settings-general-fk_settings-skeleton_settings-extended_knees = Подовжене коліно
settings-general-fk_settings-vive_emulation-title = Емуляція Vive
settings-general-fk_settings-vive_emulation-description = Емуляція проблем з трекером талії, які є у трекерів Vive. Це жарт і погіршує відстеження.
settings-general-fk_settings-vive_emulation-label = Увімкнути емуляцію Vive
## Gesture control settings (tracker tapping)
settings-general-gesture_control = Управління жестами
settings-general-gesture_control-subtitle = Скидання на основі дотику
settings-general-gesture_control-description = Дозволяє запускати скидання, торкнувшись трекера. Трекер найвищий на вашому тулубі використовується для скидання нахилу, трекер найвищий на лівій нозі використовується для повного скидання, а трекер найвищий на правій нозі використовується для скидання закріплення. Слід зазначити, що дотики повинні відбутися протягом 0,6 секунди для реєстрації.
# This is a unit: 3 taps, 2 taps, 1 tap
# $amount (Number) - Amount of taps (touches to the tracker's case)
settings-general-gesture_control-taps =
{ $amount ->
[one] 1 дотик
[few] 2 дотика
[many] { $amount } дотиків
*[other] { $amount } дотиків
}
settings-general-gesture_control-yawResetEnabled = Увімкнути дотик, щоб скинути нахил
settings-general-gesture_control-yawResetDelay = Затримка скидання нахилу
settings-general-gesture_control-yawResetTaps = Дотики для скидання нахилу
settings-general-gesture_control-fullResetEnabled = Увімкнути дотик для повного скидання
settings-general-gesture_control-fullResetDelay = Затримка повного скидання
settings-general-gesture_control-fullResetTaps = Дотики для повного скидання
settings-general-gesture_control-mountingResetEnabled = Увімкнути дотик для скидання прив'язки
settings-general-gesture_control-mountingResetDelay = Затримка скидання прив'язки
settings-general-gesture_control-mountingResetTaps = Дотики для скидання прив'язки
## Interface settings
settings-general-interface = Інтерфейс
settings-general-interface-dev_mode = Режим розробника
settings-general-interface-dev_mode-description = Цей режим може бути корисним, якщо вам потрібні поглиблені дані або для взаємодії з підключеними трекерами на більш просунутому рівні.
settings-general-interface-dev_mode-label = Режим розробника
settings-general-interface-serial_detection = Виявлення послідовного пристрою
settings-general-interface-serial_detection-description = Цей параметр відображатиме спливаюче вікно кожного разу, коли ви підключаєте новий послідовний пристрій, який може бути трекером. Це допомагає покращити процес налаштування трекера.
settings-general-interface-serial_detection-label = Виявлення послідовного пристрою
settings-general-interface-feedback_sound = Звук зворотного зв'язку
settings-general-interface-feedback_sound-description = Ця опція відтворюватиме звуковий сигнал при спрацьовуванні скидання
settings-general-interface-feedback_sound-label = Звук зворотного зв'язку
settings-general-interface-feedback_sound-volume = Гучність звуку зворотного зв'язку
settings-general-interface-theme = Варіація оформлення
settings-general-interface-lang = Виберіть мову
settings-general-interface-lang-description = Змініть мову за замовчуванням, яку ви хочете використовувати.
settings-general-interface-lang-placeholder = Виберіть мову для використання
## Serial settings
settings-serial = Послідовна консоль
# This cares about multilines
settings-serial-description =
Це інформаційна стрічка для послідовного зв'язку.
Може бути корисним, якщо вам потрібно знати, що прошивка не працює.
settings-serial-connection_lost = Підключення до послідовного пристрою втрачене, повторне підключення...
settings-serial-reboot = Перезавантажити
settings-serial-factory_reset = Скидання до заводських налаштувань
# This cares about multilines
# <b>text</b> means that the text should be bold
settings-serial-factory_reset-warning =
<b>Попередження:</b> Це скине трекер до заводських налаштувань.
Це означає, що Wi-Fi та налаштування калібрування <b>будуть втрачені!</b>
settings-serial-factory_reset-warning-ok = Я знаю, що роблю
settings-serial-factory_reset-warning-cancel = Скасувати
settings-serial-get_infos = Отримати інформацію
settings-serial-serial_select = Вибір послідовного порту
settings-serial-auto_dropdown_item = Автоматично
## OSC router settings
settings-osc-router = OSC роутер
# This cares about multilines
settings-osc-router-description =
Пересилання повідомлень OSC з іншої програми.
Корисно для використання іншої програми OSC з VRChat, наприклад.
settings-osc-router-enable = Увімкнути
settings-osc-router-enable-description = Увімкнути пересилання повідомлень.
settings-osc-router-enable-label = Увімкнути
settings-osc-router-network = Мережеві порти
# This cares about multilines
settings-osc-router-network-description =
Встановіть порти для прослуховування і відправки даних.
Вони можуть бути такими ж, як і інші порти, що використовуються на сервері SlimeVR.
settings-osc-router-network-port_in =
.label = Вхідний Порт
.placeholder = Вхідний Порт (зазвичай: 9002)
settings-osc-router-network-port_out =
.label = Вихідний Порт
.placeholder = Вихідний Порт (зазвичай: 9000)
settings-osc-router-network-address = Мережева адреса
settings-osc-router-network-address-description = Укажіть адресу для надсилання даних за адресою.
settings-osc-router-network-address-placeholder = IPV4-адреса
## OSC VRChat settings
settings-osc-vrchat = VRChat OSC трекери
# This cares about multilines
settings-osc-vrchat-description =
Змініть специфічні для VRChat налаштування для отримання даних шолому та надсилання
даних трекерів для FBT без SteamVR (наприклад, автономний Quest).
settings-osc-vrchat-enable = Увімкнути
settings-osc-vrchat-enable-description = Перемикайте відправку та отримання даних.
settings-osc-vrchat-enable-label = Увімкнути
settings-osc-vrchat-network = Мережеві порти
settings-osc-vrchat-network-description = Встановіть порти для прослуховування і відправки даних в VRChat.
settings-osc-vrchat-network-port_in =
.label = Вхідний Порт
.placeholder = Вхідний Порт (зазвичай: 9001)
settings-osc-vrchat-network-port_out =
.label = Вихідний Порт
.placeholder = Вихідний Порт (зазвичай: 9000)
settings-osc-vrchat-network-address = Мережева адреса
settings-osc-vrchat-network-address-description = Виберіть, за якою адресою надсилати дані до VRChat (перевірте налаштування Wi-Fi на своєму пристрої).
settings-osc-vrchat-network-address-placeholder = IP-адреса VRChat
settings-osc-vrchat-network-trackers = Трекери
settings-osc-vrchat-network-trackers-description = Перемикання відправку конкретних трекерів через OSC.
settings-osc-vrchat-network-trackers-chest = Груди
settings-osc-vrchat-network-trackers-hip = Бедро
settings-osc-vrchat-network-trackers-knees = Коліна
settings-osc-vrchat-network-trackers-feet = Ступні
settings-osc-vrchat-network-trackers-elbows = Лікті
## VMC OSC settings
settings-osc-vmc = Віртуальне захоплення руху
# This cares about multilines
settings-osc-vmc-description =
Змінення настройок протоколу VMC (Virtual Motion Capture)
щоб надсилати дані про кістки SlimeVR та отримувати дані про кістки з інших програм.
settings-osc-vmc-enable = Увімкнути
settings-osc-vmc-enable-description = Перемикайте відправку та отримання даних.
settings-osc-vmc-enable-label = Увімкнути
settings-osc-vmc-network = Мережеві порти
settings-osc-vmc-network-description = Встановіть порти для прослуховування і відправки даних по VMC
settings-osc-vmc-network-port_in =
.label = Вхідний Порт
.placeholder = Вхідний Порт (зазвичай: 39540)
settings-osc-vmc-network-port_out =
.label = Вихідний Порт
.placeholder = Вихідний Порт (зазвичай: 39539)
settings-osc-vmc-network-address = Мережева адреса
settings-osc-vmc-network-address-description = Виберіть, за якою адресою надсилати дані через VMC
settings-osc-vmc-network-address-placeholder = IPV4-адреса
settings-osc-vmc-vrm = Модель VRM
settings-osc-vmc-vrm-description = Завантажте модель VRM, щоб дозволити головний якір і забезпечити більш високу сумісність з іншими програмами
settings-osc-vmc-vrm-model_unloaded = Модель не завантажена
settings-osc-vmc-vrm-model_loaded =
{ $titled ->
[true] Модель завантажена: { $name }
*[other] Завантажена модель без назви
}
settings-osc-vmc-vrm-file_select = Перетягніть модель для використання або <u>знайдіть</u>
settings-osc-vmc-anchor_hip = Якір у стегон
settings-osc-vmc-anchor_hip-description = Закріпіть стеження на стегнах, корисно для сидячих VTubing. Якщо вимкнено, завантажте модель VRM.
settings-osc-vmc-anchor_hip-label = Якір у стегон
## Setup/onboarding menu
onboarding-skip = Пропустити налаштування
onboarding-continue = Продовжити
onboarding-wip = В роботі
onboarding-previous_step = Попередній крок
onboarding-setup_warning =
<b>Попередження:</b> Початкова настройка потрібна для хорошого відстеження,
це потрібно, якщо ви вперше використовуєте SlimeVR.
onboarding-setup_warning-skip = Пропустити налаштування
onboarding-setup_warning-cancel = Продовжити налаштування
## Wi-Fi setup
onboarding-wifi_creds-back = Повернутися до вступу
onboarding-wifi_creds = Введіть дані Wi-Fi
# This cares about multilines
onboarding-wifi_creds-description =
Трекери використовуватимуть ці дані для бездротового підключення.
Будь ласка, використовуйте дані, до яких ви зараз підключені.
onboarding-wifi_creds-skip = Пропустити налаштування Wi-Fi
onboarding-wifi_creds-submit = Підтвердити!
onboarding-wifi_creds-ssid =
.label = Назва Wi-Fi
.placeholder = Введіть назву Wi-Fi
onboarding-wifi_creds-password =
.label = Пароль
.placeholder = Введіть Пароль
## Mounting setup
onboarding-reset_tutorial-back = Повернутися до розділу Калібрування прив'язки
onboarding-reset_tutorial = Інструкція по скиданню
onboarding-reset_tutorial-explanation = Коли ви використовуєте свої трекери, вони можуть вийти з вирівнювання через дрейф нахилу IMU або тому, що ви могли їх фізично перемістити. Це можна виправити кількома способами.
onboarding-reset_tutorial-skip = Пропустити крок
# Cares about multiline
onboarding-reset_tutorial-0 =
Торкніться { $taps } виділеного трекера, щоб запустити скидання нахилу.
Це змусить трекери дивитися в тому ж напрямку, що і ваш шолом.
# Cares about multiline
onboarding-reset_tutorial-1 =
Торкніться { $taps } виділеного трекера, щоб ініціювати повне скидання.
Для цього потрібно стояти (i-поза). Існує затримка 3 секунди (налаштовується), перш ніж це дійсно станеться.
Це повністю скидає положення та обертання всіх ваших трекерів. Це має вирішити більшість проблем.
# Cares about multiline
onboarding-reset_tutorial-2 =
Торкніться { $taps } виділеного елемента стеження, щоб активувати скидання прив'язки.
Скидання прив'язки допомагає в тому, як трекери насправді надягнені на вас, тому, якщо ви випадково перемістили їх і змінили місце прикріплення на велику кількість, це допоможе.
Вам потрібно бути в позі, ніби ви катаєтеся на лижах, як показано на майстрі автоматичної прив'язки, і у вас є 3-секундна затримка (налаштовується), перш ніж вона спрацює.
## Setup start
onboarding-home = Ласкаво просимо до SlimeVR
onboarding-home-start = Давайте налаштуємося!
## Enter VR part of setup
onboarding-enter_vr-back = Повернутися до Прив'язки трекерів
onboarding-enter_vr-title = Час вступати у VR!
onboarding-enter_vr-description = Увімкніть усі свої трекери, а потім вступіть у VR!
onboarding-enter_vr-ready = Я готовий
## Setup done
onboarding-done-title = Все готово!
onboarding-done-description = Насолоджуйтесь досвідом трекінгу всього тіла
onboarding-done-close = Закрити налаштування
## Tracker connection setup
onboarding-connect_tracker-back = Повернутися до даних Wi-Fi
onboarding-connect_tracker-title = Підключіть трекери
onboarding-connect_tracker-description-p0 = Тепер перейдемо до найцікавішого, з'єднання усіх трекерів!
onboarding-connect_tracker-description-p1 = Просто підключіть все, що ще не підключено, через USB-порт.
onboarding-connect_tracker-issue-serial = У мене виникли проблеми з підключенням!
onboarding-connect_tracker-usb = USB-трекер
onboarding-connect_tracker-connection_status-none = Шукаємо трекери
onboarding-connect_tracker-connection_status-serial_init = Підключення до послідовного пристрою
onboarding-connect_tracker-connection_status-provisioning = Надсилання даних Wi-Fi
onboarding-connect_tracker-connection_status-connecting = Спроба підключення до Wi-Fi
onboarding-connect_tracker-connection_status-looking_for_server = Шукаю сервер
onboarding-connect_tracker-connection_status-connection_error = Не вдається підключитися до мережі Wi-Fi
onboarding-connect_tracker-connection_status-could_not_find_server = Не вдалося знайти сервер
onboarding-connect_tracker-connection_status-done = Підключено до сервера
# $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",
# we use 0 in an explicit way because there is no plural rule in english for 0, so we directly say
# if $amount is 0 then we say "No trackers connected"
onboarding-connect_tracker-connected_trackers =
{ $amount ->
[0] Трекери не підключенно
[one] 1 трекер підключенний
[few] { $amount } трекерів підключенно
[many] { $amount } трекерів підключенно
*[other] { $amount } трекерів підключенно
}
onboarding-connect_tracker-next = Я підключив усі свої трекери
## Tracker calibration tutorial
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 = Калібрування
onboarding-calibration_tutorial-status-success = Добре!
onboarding-calibration_tutorial-status-error = Трекер переміщено
## Tracker assignment tutorial
onboarding-assignment_tutorial = Як підготувати Slime трекер перед його надяганням
onboarding-assignment_tutorial-first_step = 1. Розмістіть наліпку з частиною тіла (якщо вона у вас є) на трекері відповідно до вашого вибору
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Наліпка
onboarding-assignment_tutorial-second_step = 2. Прикріпіть ремінь до трекера, зберігаючи гачок і петльову сторону лицьової сторони ремінця в такій орієнтації:
onboarding-assignment_tutorial-second_step-continuation = Гачок і петльова сторона для подовжувача повинні бути в такій орієнтації:
onboarding-assignment_tutorial-done = Я наклеїв наліпки і закріпив ремінці!
## Tracker assignment setup
onboarding-assign_trackers-back = Повернутися до даних Wi-Fi
onboarding-assign_trackers-title = Призначити трекери
onboarding-assign_trackers-description = Давайте виберемо, який трекер куди йде. Натисніть на місце, де ви хочете розмістити трекер
# Look at translation of onboarding-connect_tracker-connected_trackers on how to use plurals
# $assigned (Number) - Trackers that have been assigned a body part
# $trackers (Number) - Trackers connected to the server
onboarding-assign_trackers-assigned =
{ $trackers ->
[one] { $assigned } з 1 трекеру призначенно
[few] { $assigned } з { $trackers } трекерів призначенно
[many] { $assigned } з { $trackers } трекерів призначенно
*[other] { $assigned } з { $trackers } трекерів призначенно
}
onboarding-assign_trackers-advanced = Відобразити розширені розташування призначень
onboarding-assign_trackers-next = Я призначив усі трекери
## Tracker assignment warnings
# Note for devs, number is used for representing boolean states per bit.
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_FOOT =
{ $unassigned ->
[0] Ліва нога призначенна, але треба ще ліва щиколотка, ліве стегно та на вибір груди, бедро або талія повинні бути призначенні
[1] Ліва ступня призначенна, але в тебе повинно бути ліве стегно і на вибір груди, бедро або талія теж призначенні
[2] Ліва ступня призначенна, але в тебе повинно бути ще ліва щиколотка та на вибір груди, бедро або талія теж призначенні
[3] Ліва ступня призначенна, але тобі ще треба на вибір груди, бедро або талія теж призначенні
[4] Ліва ступня призначенна, але тобі ще потрібно ліва щиколотка і ліве стегно теж призначенні
[5] Ліва ступня призначенна, але тобі ще потрібно ліве стегно теж призначити
[6] Ліва ступня призначенна, але тобі ще треба ліву щиколотку теж призначити
*[other] Ліва ступня призначенна, але тобі ще треба Невідома кількість непризначенних частин тіла теж призначенні
}
## Tracker mounting method choose
onboarding-choose_mounting = Який метод калібрування закріплення використовувати?
# Multiline text
onboarding-choose_mounting-description = Орієнтація кріплення коригується для розміщення трекерів на вашому тілі.
onboarding-choose_mounting-auto_mounting = Автоматична прив'язка
# Italized text
onboarding-choose_mounting-auto_mounting-label = Експериментальний
onboarding-choose_mounting-auto_mounting-description = Це автоматично визначить напрямки прив'язки для всіх ваших трекерів з 2 поз
onboarding-choose_mounting-manual_mounting = Ручна прив'язка
# Italized text
onboarding-choose_mounting-manual_mounting-label = Рекомендується
onboarding-choose_mounting-manual_mounting-description = Це дозволить вибрати напрямок прив'язки вручну для кожного трекера
## Tracker manual mounting setup
onboarding-manual_mounting-back = Повернутися до VR
onboarding-manual_mounting = Ручне закріплення
onboarding-manual_mounting-description = Натисніть на кожен трекер і виберіть, в який бік вони прив'язані
onboarding-manual_mounting-auto_mounting = Автоматична прив'язка
onboarding-manual_mounting-next = Наступний крок
## Tracker automatic mounting setup
onboarding-automatic_mounting-back = Повернутися до VR
onboarding-automatic_mounting-next = Наступний крок
onboarding-automatic_mounting-prev_step = Попередній крок
onboarding-automatic_mounting-done-restart = Спробуйте знову
## Tracker proportions method choose
## Tracker manual proportions setup
## Tracker automatic proportions setup
onboarding-automatic_proportions-prev_step = Попередній крок
onboarding-automatic_proportions-requirements-next = Я ознайомився з вимогами
onboarding-automatic_proportions-start_recording-title = Приготуйтеся рухатися
onboarding-automatic_proportions-start_recording-next = Почати запис
onboarding-automatic_proportions-recording-title = ЗАПИС
onboarding-automatic_proportions-recording-description-p1 = Повторюйте рухи, показані нижче:
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =
{ $time ->
[one] залишилась { $time } секунда
[few] залишилось { $time } секунди
[many] залишилось { $time } секунд
*[other] залишилось { $time } секунд
}
onboarding-automatic_proportions-verify_results-title = Перевірити результати
onboarding-automatic_proportions-verify_results-processing = Обробка результату
## Home
## Status system

View File

@@ -13,7 +13,7 @@ websocket-connection_lost = 与服务器的连接丢失,正在尝试重新连
## Update notification
version_update-title = 新版本可用:{ $version }
version_update-description = 点击“更新”将为您下载SlimeVR安装程序。
version_update-description = 点击“{ version_update-update }”将为您下载 SlimeVR 安装程序。
version_update-update = 更新
version_update-close = 关闭
@@ -53,8 +53,8 @@ skeleton_bone-NONE = 无
skeleton_bone-HEAD = 头部偏移
skeleton_bone-NECK = 颈部长度
skeleton_bone-torso_group = 躯干长度
skeleton_bone-CHEST = 胸部长度
skeleton_bone-CHEST_OFFSET = 胸部偏移
skeleton_bone-CHEST = 胸部长度
skeleton_bone-WAIST = 腰部长度
skeleton_bone-HIP = 髋部长度
skeleton_bone-HIP_OFFSET = 髋部偏移
@@ -526,7 +526,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = 返回到佩戴校准
onboarding-reset_tutorial = 重置教程
onboarding-reset_tutorial-description = 踪器在使用时可能会由于IMU的偏航漂移而失准,或者可能因为您对它们进行了物理上的移动。您有几种方法来解决这个问题。
onboarding-reset_tutorial-explanation = 踪器在使用时可能会由于IMU的航向角漂移或是因为您移动了它们而失准。您有几种方法来解决这个问题。
onboarding-reset_tutorial-skip = 跳过步骤
# Cares about multiline
onboarding-reset_tutorial-0 =
@@ -597,7 +597,7 @@ onboarding-connect_tracker-next = 所有的追踪器都连接好了
onboarding-calibration_tutorial = IMU校准教程
onboarding-calibration_tutorial-subtitle = 这将有助于减少追踪器漂移!
onboarding-calibration_tutorial-description = 每次开启追踪器时,它们都需要在平坦的表面上放置片刻以进行自校准。你可以通过点击“校准”按钮来手动校准, <b>校准过程中不要移动它们</b>
onboarding-calibration_tutorial-description = 每次开启追踪器时,它们都需要在平坦的表面上放置片刻以进行自校准。你可以通过点击“{ onboarding-calibration_tutorial-calibrate }”按钮来手动校准, <b>校准过程中不要移动追踪器</b>
onboarding-calibration_tutorial-calibrate = 我已经把追踪器放在桌子上了
onboarding-calibration_tutorial-status-waiting = 等待你的操作
onboarding-calibration_tutorial-status-calibrating = 校准中
@@ -701,11 +701,11 @@ onboarding-choose_mounting = 使用哪种方法校准佩戴朝向?
onboarding-choose_mounting-description = 佩戴方向校准用于确定您身上的追踪器的朝向。
onboarding-choose_mounting-auto_mounting = 自动设置佩戴方向
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = 推荐
onboarding-choose_mounting-auto_mounting-label = 实验功能
onboarding-choose_mounting-auto_mounting-description = 这将需要你做2个动作以自动检测所有追踪器的佩戴方向
onboarding-choose_mounting-manual_mounting = 手动设置佩戴方向
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = 如果你清楚自己在做什么
onboarding-choose_mounting-manual_mounting-label = 推荐
onboarding-choose_mounting-manual_mounting-description = 这将需要你手动选择每个追踪器的佩戴方向
## Tracker manual mounting setup
@@ -726,7 +726,7 @@ onboarding-automatic_mounting-next = 下一步
onboarding-automatic_mounting-prev_step = 上一步
onboarding-automatic_mounting-done-title = 佩戴方向已校准。
onboarding-automatic_mounting-done-description = 你的佩戴方向校准完成!
onboarding-automatic_mounting-done-restart = 返回以开始
onboarding-automatic_mounting-done-restart = 再试一次
onboarding-automatic_mounting-mounting_reset-title = 佩戴重置
onboarding-automatic_mounting-mounting_reset-step-0 = 1. 双腿弯曲以滑雪的姿势蹲下,上身向前倾斜,手臂弯曲。
onboarding-automatic_mounting-mounting_reset-step-1 = 按下佩戴重置按钮并等待 3 秒钟,然后追踪器的佩戴方向将被重置。
@@ -752,7 +752,7 @@ onboarding-choose_proportions-manual_proportions = 手动调整身体比例
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = 用于精细调整
onboarding-choose_proportions-manual_proportions-description = 这将需要你手动修改以调整你的身体比例
onboarding-choose_proportions-save = 储存身体比例到文件
onboarding-choose_proportions-export = 导出身体比例
onboarding-choose_proportions-file_type = 身体比例文件
## Tracker manual proportions setup

View File

@@ -13,7 +13,7 @@ websocket-connection_lost = 與伺服器的連線已中斷,正在嘗試重新
## Update notification
version_update-title = 有可用的新版本:{ $version }
version_update-description = 按下「更新」將為您下載 SlimeVR 安裝程式。
version_update-description = 按下「{ version_update-update }」將為您下載 SlimeVR 安裝程式。
version_update-update = 更新
version_update-close = 關閉
@@ -36,6 +36,7 @@ body_part-RIGHT_HAND = 右手
body_part-RIGHT_UPPER_LEG = 右大腿
body_part-RIGHT_LOWER_LEG = 右小腿
body_part-RIGHT_FOOT = 右腳
body_part-UPPER_CHEST = 上胸
body_part-CHEST = 胸部
body_part-WAIST = 腰部
body_part-HIP = 臀部
@@ -53,8 +54,9 @@ skeleton_bone-NONE = 無
skeleton_bone-HEAD = 頭部偏移
skeleton_bone-NECK = 頸部長度
skeleton_bone-torso_group = 軀幹長度
skeleton_bone-CHEST = 胸長度
skeleton_bone-UPPER_CHEST = 胸長度
skeleton_bone-CHEST_OFFSET = 胸部偏移
skeleton_bone-CHEST = 胸部長度
skeleton_bone-WAIST = 腰部長度
skeleton_bone-HIP = 臀部長度
skeleton_bone-HIP_OFFSET = 臀部偏移
@@ -230,6 +232,7 @@ tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part }右大腿?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part }右小腿?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part }右腳?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part }右控制器?
tracker_selection_menu-UPPER_CHEST = { -tracker_selection-part }上胸?
tracker_selection_menu-CHEST = { -tracker_selection-part }胸部?
tracker_selection_menu-WAIST = { -tracker_selection-part }腰部?
tracker_selection_menu-HIP = { -tracker_selection-part }臀部?
@@ -524,7 +527,7 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = 返回到配戴校正
onboarding-reset_tutorial = 重置教學
onboarding-reset_tutorial-description = 使用追蹤器時會產生偏移,可能是因為慣性測量單元 (IMU) 會出現左右飄移,或是您移動了追蹤器所造成的。您有幾種方法來修正這個問題。
onboarding-reset_tutorial-explanation = 當您使用追蹤器時追蹤器可能會跑位,原因來自於慣性測量單元 (IMU) 產生了左右飄移,或是您移動了追蹤器的實體位置。您有幾種方法來修正這個問題。
onboarding-reset_tutorial-skip = 跳過本步驟
# Cares about multiline
onboarding-reset_tutorial-0 =
@@ -595,7 +598,7 @@ onboarding-connect_tracker-next = 所有的追蹤器都連接好了
onboarding-calibration_tutorial = IMU 校正教學
onboarding-calibration_tutorial-subtitle = 進行這項操作可以有效減少追蹤器發生飄移的機會
onboarding-calibration_tutorial-description = 每次在打開追蹤器的開關時,需要將追蹤器放置在平面一會兒來進行自動校正。您也可以透過按下“校正”按鈕來進行手動校正,<b>校正過程中請勿移動追蹤器</b>。
onboarding-calibration_tutorial-description = 每次在打開追蹤器的開關時,需要將追蹤器放置在平面一會兒來進行自動校正。您也可以透過按下「{ onboarding-calibration_tutorial-calibrate }」按鈕來進行手動校正,<b>校正過程中請勿移動追蹤器</b>。
onboarding-calibration_tutorial-calibrate = 追蹤器已經放置在桌上了
onboarding-calibration_tutorial-status-waiting = 正在等待您完成動作
onboarding-calibration_tutorial-status-calibrating = 校正中
@@ -608,7 +611,7 @@ onboarding-assignment_tutorial = 戴上 Slime 追蹤器前的準備事項
onboarding-assignment_tutorial-first_step = 1. 若有標示身體部位的貼紙,可在您所要分配使用的追蹤器上貼上。
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = 貼紙
onboarding-assignment_tutorial-second_step = 2. 將綁帶有魔鬼氈的一面,依照下圖所示的方向穿過追蹤器:
onboarding-assignment_tutorial-second_step = 2. 將綁帶有魔鬼氈(魔術貼)的一面,依照下圖所示的方向穿過追蹤器:
onboarding-assignment_tutorial-second_step-continuation = 延伸追蹤器應照下圖所示:
onboarding-assignment_tutorial-done = 我把貼紙跟綁帶都弄上了
@@ -699,11 +702,11 @@ onboarding-choose_mounting = 要使用哪一種配戴校正方式?
onboarding-choose_mounting-description = 配戴校正可以校正追蹤器放在身上的位置。
onboarding-choose_mounting-auto_mounting = 自動配戴校正
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = 推薦使用
onboarding-choose_mounting-auto_mounting-label = 實驗功能
onboarding-choose_mounting-auto_mounting-description = 本選項會透過兩個身體姿勢,判斷所有追蹤器的配戴方位
onboarding-choose_mounting-manual_mounting = 手動配戴校正
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = 如果你清楚你要做什麼的話
onboarding-choose_mounting-manual_mounting-label = 推薦使用
onboarding-choose_mounting-manual_mounting-description = 本選項可以讓你選擇每個追蹤器的配戴方位
## Tracker manual mounting setup
@@ -724,7 +727,7 @@ onboarding-automatic_mounting-next = 下一步
onboarding-automatic_mounting-prev_step = 上一步
onboarding-automatic_mounting-done-title = 配戴方向已校正。
onboarding-automatic_mounting-done-description = 你的配戴方向校準完成!
onboarding-automatic_mounting-done-restart = 返回以開始
onboarding-automatic_mounting-done-restart = 再試一次
onboarding-automatic_mounting-mounting_reset-title = 配戴重置
onboarding-automatic_mounting-mounting_reset-step-0 = 1. 雙腿彎曲以滑雪的姿勢蹲下,上身向前傾斜,手臂彎曲。
onboarding-automatic_mounting-mounting_reset-step-1 = 2. 按下「配戴重置」按鈕並等待 3 秒鐘,追蹤器的配戴方向將被重置。
@@ -750,7 +753,7 @@ onboarding-choose_proportions-manual_proportions = 手動軀幹比例校正
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = 適合進行微調
onboarding-choose_proportions-manual_proportions-description = 本選項可以讓你直接修改軀幹比例的設定值
onboarding-choose_proportions-save = 儲存軀幹比例
onboarding-choose_proportions-export = 匯出軀幹比例
onboarding-choose_proportions-file_type = 軀幹比例描述檔
## Tracker manual proportions setup
@@ -779,7 +782,7 @@ onboarding-automatic_proportions-requirements-description =
你需要穿戴上追蹤器與頭戴顯示器。
你的追蹤器與頭戴顯示器都已經連接到 SlimeVR 伺服器。
你的追蹤器與頭戴顯示器在 SlimeVR 伺服器中運作正常。
你的頭戴顯示器會回報定位資料給 SlimeVR 伺服器(通常為執行 SteamVR 並透過 SlimeVR 的 SteamVR 附加元件來連接 SlimeVR
你的頭戴顯示器會回報定位資料給 SlimeVR 伺服器(通常為執行 SteamVR 並透過 SlimeVR 的 SteamVR 驅動程式來連接 SlimeVR
onboarding-automatic_proportions-requirements-next = 我已閱讀使用需求
onboarding-automatic_proportions-start_recording-title = 準備擺動作囉
onboarding-automatic_proportions-start_recording-description = 我們現在要記錄一些特定的姿勢和動作,將會在下一個畫面中提示。當按鈕被按下時,準備好開始!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 998 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 758 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

View File

@@ -30,7 +30,8 @@ serde_json = "1"
serde = { version = "1", features = ["derive"] }
tauri = { version = "1.4", features = ["devtools", "dialog", "dialog-save", "fs-all", "os-all", "path-all", "shell-execute", "shell-open", "window-close", "window-maximize", "window-minimize", "window-set-resizable", "window-set-size", "window-set-title", "window-start-dragging", "window-unmaximize", "window-unminimize"] }
tauri-runtime = "0.14"
pretty_env_logger = "0.5"
flexi_logger = "0.25"
log-panics = { version = "2", features = ["with-backtrace"] }
log = "0.4"
clap = { version = "4.0.29", features = ["derive"] }
clap-verbosity-flag = "2"
@@ -38,7 +39,7 @@ rand = "0.8.5"
tempfile = "3"
which = "4.3"
glob = "0.3"
open = "4"
open = "5"
shadow-rs = { version = "0.23", default-features = false }
const_format = "0.2.30"
cfg-if = "1"

View File

@@ -9,6 +9,7 @@ use std::time::Duration;
use std::time::Instant;
use clap::Parser;
use color_eyre::Result;
use state::WindowState;
use tauri::api::process::{Command, CommandChild};
use tauri::Manager;
@@ -38,22 +39,55 @@ fn update_window_state(
Ok(())
}
fn main() {
#[tauri::command]
fn logging(msg: String) {
log::info!(target: "webview", "{}", msg)
}
#[tauri::command]
fn erroring(msg: String) {
log::error!(target: "webview", "{}", msg)
}
#[tauri::command]
fn warning(msg: String) {
log::warn!(target: "webview", "{}", msg)
}
fn main() -> Result<()> {
log_panics::init();
let hook = panic::take_hook();
// Make an error dialog box when panicking
panic::set_hook(Box::new(|panic_info| {
println!("{}", panic_info);
panic::set_hook(Box::new(move |panic_info| {
show_error(&panic_info.to_string());
hook(panic_info);
}));
let cli = Cli::parse();
let tauri_context = tauri::generate_context!();
// Set up loggers and global handlers
{
if std::env::var_os("RUST_LOG").is_none() {
std::env::set_var("RUST_LOG", "info")
}
pretty_env_logger::init();
}
let _logger = {
use flexi_logger::{
Age, Cleanup, Criterion, Duplicate, FileSpec, Logger, Naming, WriteMode,
};
use tauri::api::path::app_log_dir;
Logger::try_with_env_or_str("info")?
.log_to_file(FileSpec::default().directory(
app_log_dir(tauri_context.config()).expect("We need a log dir"),
))
.format_for_files(util::logger_format)
.format_for_stderr(util::logger_format)
.rotate(
Criterion::Age(Age::Day),
Naming::Timestamps,
Cleanup::KeepLogFiles(2),
)
.duplicate_to_stderr(Duplicate::All)
.write_mode(WriteMode::BufferAndFlush)
.start()?
};
// Ensure child processes die when spawned on windows
// and then check for WebView2's existence
@@ -86,7 +120,7 @@ fn main() {
if confirm {
open::that("https://docs.slimevr.dev/server-setup/installing-and-connecting.html#install-the-latest-slimevr-installer").unwrap();
}
return;
return Ok(());
}
}
@@ -106,7 +140,7 @@ fn main() {
.or_else(|| valid_java_paths().first().map(|x| x.0.to_owned()));
let Some(java_bin) = java_bin else {
show_error(&format!("Couldn't find a compatible Java version, please download Java {} or higher", MINIMUM_JAVA_VERSION));
return;
return Ok(());
};
log::info!("Using Java binary: {:?}", java_bin);
@@ -124,7 +158,12 @@ fn main() {
let exit_flag_terminated = exit_flag.clone();
let build_result = tauri::Builder::default()
.invoke_handler(tauri::generate_handler![update_window_state])
.invoke_handler(tauri::generate_handler![
update_window_state,
logging,
erroring,
warning
])
.setup(move |app| {
let window_state =
WindowState::open_state(app.path_resolver().app_config_dir().unwrap())
@@ -190,7 +229,7 @@ fn main() {
WindowEvent::Resized(_) => std::thread::sleep(std::time::Duration::from_nanos(1)),
_ => (),
})
.build(tauri::generate_context!());
.build(tauri_context);
match build_result {
Ok(app) => {
app.run(move |app_handle, event| match event {
@@ -246,4 +285,6 @@ fn main() {
show_error(&error.to_string());
}
}
Ok(())
}

View File

@@ -10,6 +10,8 @@ use std::{
use clap::Parser;
use const_format::concatcp;
use flexi_logger::{DeferredNow, style};
use log::Record;
use shadow_rs::shadow;
use tempfile::Builder;
@@ -216,3 +218,25 @@ pub fn valid_java_paths() -> Vec<(OsString, i32)> {
})
.collect()
}
pub fn logger_format(
w: &mut dyn std::io::Write,
_now: &mut DeferredNow,
record: &Record,
) -> Result<(), std::io::Error> {
let level = record.level();
let module_path = record.module_path().unwrap_or("<unnamed>");
// optionally print target
let target = if module_path.starts_with(record.target()) {
"".to_string()
} else {
format!(", {}", record.target())
};
write!(
w,
"{} [{}{target}] {}",
style(level).paint(level.to_string()),
record.module_path().unwrap_or("<unnamed>"),
style(level).paint(record.args().to_string())
)
}

View File

@@ -30,7 +30,7 @@
"deb": {
"depends": ["openjdk-17-jre-headless"],
"files": {
"/usr/share/slimevr/slimevr.jar": "../../server/build/libs/slimevr.jar"
"/usr/share/slimevr/slimevr.jar": "../../server/desktop/build/libs/slimevr.jar"
}
},
"appimage": {

View File

@@ -50,10 +50,13 @@ import { open } from '@tauri-apps/api/shell';
import semver from 'semver';
import { useBreakpoint } from './hooks/breakpoint';
import { VRModePage } from './components/vr-mode/VRModePage';
import { InterfaceSettings } from './components/settings/pages/InterfaceSettings';
import { error, log } from './utils/logging';
export const GH_REPO = 'SlimeVR/SlimeVR-Server';
export const VersionContext = createContext('');
export const DOCS_SITE = 'https://docs.slimevr.dev/';
export const DOCS_SITE = 'https://docs.slimevr.dev';
export const SLIMEVR_DISCORD = 'https://discord.gg/slimevr';
function Layout() {
const { loading } = useConfig();
@@ -103,6 +106,7 @@ function Layout() {
<Route path="osc/router" element={<OSCRouterSettings />} />
<Route path="osc/vrchat" element={<VRCOSCSettings />} />
<Route path="osc/vmc" element={<VMCSettings />} />
<Route path="interface" element={<InterfaceSettings />} />
</Route>
<Route
path="/onboarding"
@@ -166,19 +170,19 @@ export default function App() {
setUpdateFound(releases[0].tag_name);
}
}
fetchReleases().catch(() => console.error('failed to fetch releases'));
fetchReleases().catch(() => error('failed to fetch releases'));
}, []);
if (window.__TAURI_METADATA__) {
useEffect(() => {
os.type()
.then((type) => document.body.classList.add(type.toLowerCase()))
.catch(console.error);
.catch(error);
return () => {
os.type()
.then((type) => document.body.classList.remove(type.toLowerCase()))
.catch(console.error);
.catch(error);
};
}, []);
}
@@ -192,6 +196,7 @@ export default function App() {
if ('stderr' === eventType) {
// This strange invocation is what lets us lose the line information in the console
// See more here: https://stackoverflow.com/a/48994308
// These two are fine to keep with console.log, they are server logs
setTimeout(
console.log.bind(
console,
@@ -210,11 +215,11 @@ export default function App() {
)
);
} else if (eventType === 'error') {
console.error('Error: %s', s);
error('Error: %s', s);
} else if (eventType === 'terminated') {
console.error('Server Process Terminated: %s', s);
error('Server Process Terminated: %s', s);
} else if (eventType === 'other') {
console.log('Other process event: %s', s);
log('Other process event: %s', s);
}
}
);

View File

@@ -0,0 +1,25 @@
import { useLocalization } from '@fluent/react';
import { ClearMountingResetRequestT, RpcMessage } from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { TrashIcon } from './commons/icon/TrashIcon';
export function ClearMountingButton() {
const { l10n } = useLocalization();
const { sendRPCPacket } = useWebsocketAPI();
const clearMounting = () => {
const record = new ClearMountingResetRequestT();
sendRPCPacket(RpcMessage.ClearMountingResetRequest, record);
};
return (
<BigButton
text={l10n.getString('widget-clear_mounting')}
icon={<TrashIcon width={20} />}
onClick={clearMounting}
>
{}
</BigButton>
);
}

View File

@@ -77,7 +77,7 @@ export function MainLayoutRoute({
>
<div
className={classNames(
'flex flex-col rounded-xl w-full overflow-hidden mobile:overflow-y-auto',
'flex flex-col rounded-xl w-full overflow-clip mobile:overflow-y-auto',
background && 'bg-background-70'
)}
>

View File

@@ -6,6 +6,7 @@ import { Typography } from './commons/Typography';
import { open } from '@tauri-apps/api/shell';
import semver from 'semver';
import { GH_REPO, VersionContext } from '../App';
import { error } from '../utils/logging';
export function VersionUpdateModal() {
const { l10n } = useLocalization();
@@ -24,7 +25,7 @@ export function VersionUpdateModal() {
);
}
} catch {
console.error('failed to parse new version');
error('failed to parse new version');
}
return (

View File

@@ -10,17 +10,19 @@ import { useConfig } from '../hooks/config';
import {
ResetType,
RpcMessage,
SettingsRequestT,
SettingsResponseT,
StatusData,
} from 'solarxr-protocol';
import { useMemo, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { parseStatusToLocale, useStatusContext } from '../hooks/status-system';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useAppContext } from '../hooks/app';
import { ClearMountingButton } from './ClearMountingButton';
export function WidgetsComponent() {
const { config } = useConfig();
const { useRPCPacket } = useWebsocketAPI();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [driftCompensationEnabled, setDriftCompensationEnabled] =
useState(false);
const { trackers } = useAppContext();
@@ -31,6 +33,10 @@ export function WidgetsComponent() {
[statuses]
);
useEffect(() => {
sendRPCPacket(RpcMessage.SettingsRequest, new SettingsRequestT());
}, []);
useRPCPacket(RpcMessage.SettingsResponse, (settings: SettingsResponseT) => {
if (settings.driftCompensation != null)
setDriftCompensationEnabled(settings.driftCompensation.enabled);
@@ -41,9 +47,8 @@ export function WidgetsComponent() {
<div className="grid grid-cols-2 gap-2 w-full [&>*:nth-child(odd):last-of-type]:col-span-full">
<ResetButton type={ResetType.Yaw} variant="big"></ResetButton>
<ResetButton type={ResetType.Full} variant="big"></ResetButton>
{config?.debug && (
<ResetButton type={ResetType.Mounting} variant="big"></ResetButton>
)}
<ResetButton type={ResetType.Mounting} variant="big"></ResetButton>
<ClearMountingButton></ClearMountingButton>
<BVHButton></BVHButton>
<TrackingPauseButton></TrackingPauseButton>
{driftCompensationEnabled && (
@@ -53,7 +58,7 @@ export function WidgetsComponent() {
<div className="w-full">
<OverlayWidget></OverlayWidget>
</div>
<div className="w-full flex flex-col max-h-[33%] gap-3 overflow-y-auto mb-2">
<div className="w-full flex flex-col gap-3 mb-2">
{unprioritizedStatuses.map((status) => (
<Localized
id={`status_system-${StatusData[status.dataType]}`}

View File

@@ -0,0 +1,14 @@
import { open } from '@tauri-apps/api/shell';
import { ReactNode } from 'react';
export function A({ href, children }: { href: string; children?: ReactNode }) {
return (
<a
href="javascript:void(0)"
onClick={() => open(href).catch(() => window.open(href, '_blank'))}
className="underline"
>
{children}
</a>
);
}

View File

@@ -19,7 +19,7 @@ export function BigButton({
{...props}
type="button"
className={classNames(
'flex flex-col justify-center rounded-md py-3 gap-1 px-3 cursor-pointer items-center ',
'flex flex-col justify-center rounded-md py-3 gap-1 px-3 cursor-pointer items-center',
{
'bg-background-60 hover:bg-background-60 cursor-not-allowed text-background-40 fill-background-40':
disabled,
@@ -30,7 +30,7 @@ export function BigButton({
)}
>
<div className="flex justify-around">{icon}</div>
<div className="flex text-default flex-grow">{text}</div>
<div className="flex text-default flex-grow items-center">{text}</div>
</button>
);
}

View File

@@ -14,6 +14,7 @@ import { SlimeVRIcon } from './icon/SlimeVRIcon';
import { UpperArmIcon } from './icon/UpperArmIcon';
import { UpperLegIcon } from './icon/UpperLegIcon';
import { WaistIcon } from './icon/WaistIcon';
import { UpperChestIcon } from './icon/UpperChestIcon';
// All body parts that are right or left, are by default left!
export const mapPart: Record<
@@ -26,6 +27,9 @@ export const mapPart: Record<
currentLocales: string[];
}) => JSX.Element
> = {
[BodyPart.UPPER_CHEST]: ({ width }) => (
<UpperChestIcon width={width}></UpperChestIcon>
),
[BodyPart.CHEST]: ({ width }) => <ChestIcon width={width}></ChestIcon>,
[BodyPart.HEAD]: ({ width }) => <HeadsetIcon width={width}></HeadsetIcon>,
[BodyPart.HIP]: ({ width }) => <HipIcon width={width}></HipIcon>,
@@ -80,6 +84,9 @@ export const mapPart: Record<
<UpperLegIcon width={width} flipped></UpperLegIcon>
),
[BodyPart.WAIST]: ({ width }) => <WaistIcon width={width}></WaistIcon>,
[BodyPart.ACCESSORY]: ({ width }) => (
<SlimeVRIcon width={width}></SlimeVRIcon>
),
};
export function BodyPartIcon({

View File

@@ -1,7 +1,7 @@
import classNames from 'classnames';
import React, { ReactNode, useMemo } from 'react';
import { NavLink } from 'react-router-dom';
import { LoaderIcon } from './icon/LoaderIcon';
import { LoaderIcon, SlimeState } from './icon/LoaderIcon';
function ButtonContent({
loading,
@@ -29,7 +29,7 @@ function ButtonContent({
</div>
{loading && (
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center fill-background-10">
<LoaderIcon youSpinMeRightRoundBabyRightRound></LoaderIcon>
<LoaderIcon slimeState={SlimeState.JUMPY}></LoaderIcon>
</div>
)}
</>

View File

@@ -1,11 +1,17 @@
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import { Control, Controller } from 'react-hook-form';
import { a11yClick } from '../utils/a11y';
import {
Control,
Controller,
UseFormGetValues,
useWatch,
} from 'react-hook-form';
import { a11yClick } from '../../utils/a11y';
export interface DropdownItem {
label: string;
value: string;
fontName?: string;
}
export type DropdownDirection = 'up' | 'down';
@@ -17,6 +23,7 @@ export function Dropdown({
display = 'fit',
placeholder,
control,
getValues,
name,
items = [],
}: {
@@ -26,13 +33,29 @@ export function Dropdown({
display?: 'fit' | 'block';
placeholder: string;
control: Control<any>;
getValues: UseFormGetValues<any>;
name: string;
items: DropdownItem[];
}) {
const itemRefs: Record<string, HTMLLIElement> = {};
const [isOpen, setOpen] = useState(false);
const formValue = {
...{ value: useWatch({ control, name }) as string },
...{ value: getValues(name) as string },
};
useEffect(() => {
if (!isOpen) return;
const curItem = itemRefs[formValue.value];
const dropdownParent = curItem
? (curItem.closest('.dropdown-scroll') as HTMLElement | null)
: null;
if (curItem && dropdownParent) {
dropdownParent.scroll({
top: curItem.offsetTop - dropdownParent.offsetHeight / 2,
});
}
function onWheelEvent() {
if (isOpen && !document.querySelector('div.dropdown-scroll:hover')) {
setOpen(false);
@@ -55,9 +78,9 @@ export function Dropdown({
const isInDropdownScroll = document
.querySelector('div.dropdown-scroll')
?.contains(event.target as HTMLDivElement);
const isInDropdown = document
.querySelector('div.dropdown')
?.contains(event.target as HTMLDivElement);
const isInDropdown = !!(event.target as HTMLDivElement).closest(
'.dropdown'
);
if (isOpen && !isInDropdownScroll && !isInDropdown) {
setOpen(false);
}
@@ -108,7 +131,7 @@ export function Dropdown({
onKeyDown={(ev) => a11yClick(ev) && setOpen((open) => !open)}
tabIndex={0}
>
<div className="flex-grow">
<div className="flex-grow text-standard">
{items.find((i) => i.value == value)?.label || placeholder}
</div>
<div
@@ -139,7 +162,7 @@ export function Dropdown({
<div
className={classNames(
'absolute z-10 rounded shadow min-w-max max-h-[50vh]',
'overflow-y-auto dropdown-scroll',
'overflow-y-auto dropdown-scroll overflow-x-hidden',
display === 'fit' && 'w-fit',
display === 'block' && 'w-full',
direction === 'up' && 'bottom-[45px]',
@@ -151,21 +174,20 @@ export function Dropdown({
alignment === 'left' && 'left-0'
)}
>
<ul className="py-1 text-sm flex flex-col ">
<ul className="py-1 text-sm flex flex-col">
{items.map((item) => (
<li
style={item.fontName ? { fontFamily: item.fontName } : {}}
className={classNames(
'py-2 px-4 min-w-max cursor-pointer pr-2',
'py-2 px-4 min-w-max cursor-pointer',
variant == 'primary' &&
'hover:bg-background-50 text-background-20 hover:text-background-10',
'checked-hover:bg-background-50 text-background-20 ' +
'checked-hover:text-background-10',
variant == 'secondary' &&
'hover:bg-background-60 text-background-20 hover:text-background-10',
'checked-hover:bg-background-60 text-background-20 ' +
'checked-hover:text-background-10',
variant == 'tertiary' &&
value !== item.value &&
'bg-accent-background-30 hover:bg-accent-background-20',
variant == 'tertiary' &&
value === item.value &&
'bg-accent-background-20'
'bg-accent-background-30 checked-hover:bg-accent-background-20'
)}
onClick={() => {
onChange(item.value);
@@ -176,8 +198,10 @@ export function Dropdown({
onChange(item.value);
setOpen(false);
}}
ref={(ref) => (ref ? (itemRefs[item.value] = ref) : {})}
key={item.value}
tabIndex={0}
data-checked={item.value === value}
>
{item.label}
</li>

View File

@@ -15,9 +15,11 @@ export function LangSelector({
const { changeLocales } = useContext(LangContext);
const { l10n } = useLocalization();
const { config, setConfig } = useConfig();
const { control, watch, handleSubmit } = useForm<{ lang: string }>({
defaultValues: { lang: config?.lang || 'en' },
});
const { control, watch, handleSubmit, getValues } = useForm<{ lang: string }>(
{
defaultValues: { lang: config?.lang || 'en' },
}
);
const languagesItems = useMemo(
() => langs.map(({ key, name }) => ({ label: name, value: key })),
@@ -37,6 +39,7 @@ export function LangSelector({
return (
<Dropdown
control={control}
getValues={getValues}
name="lang"
placeholder={l10n.getString(
'settings-general-interface-lang-placeholder'

View File

@@ -10,6 +10,7 @@ export function NumberSelector({
min,
max,
step,
disabled = false,
}: {
label: string;
valueLabelFormat?: (value: number) => string;
@@ -18,6 +19,7 @@ export function NumberSelector({
min: number;
max: number;
step: number | ((value: number, add: boolean) => number);
disabled?: boolean;
}) {
const stepFn =
typeof step === 'function'
@@ -38,12 +40,12 @@ export function NumberSelector({
variant="tertiary"
rounded
onClick={() => onChange(stepFn(value, false))}
disabled={stepFn(value, false) < min}
disabled={stepFn(value, false) < min || disabled}
>
-
</Button>
</div>
<div className="flex flex-grow justify-center items-center w-10">
<div className="flex flex-grow justify-center items-center w-10 text-standard">
{valueLabelFormat ? valueLabelFormat(value) : value}
</div>
<div className="flex">
@@ -51,7 +53,7 @@ export function NumberSelector({
variant="tertiary"
rounded
onClick={() => onChange(stepFn(value, true))}
disabled={stepFn(value, true) > max}
disabled={stepFn(value, true) > max || disabled}
>
+
</Button>

View File

@@ -12,9 +12,16 @@ export function PersonFrontIcon({ width }: { width?: number }) {
<image
height={'105%'}
x="8.5%"
href="/images/front-standing-pose.png"
href="/images/front-standing-pose.webp"
></image>
{/* <path d="M84.53 224.074C83.953 230.874 88.569 266.874 90.951 280.984C92.085 287.671 95.195 298.565 94.076 304.349C92.476 312.411 92.017 322.843 92.896 328.918C93.451 332.607 95.196 349.618 92.696 355.845C91.389 359.108 88.996 375.832 88.996 375.832C82.756 391.587 86.278 390.812 86.278 390.812C88.21 393.183 91.519 390.998 91.519 390.998C92.1549 391.464 92.9388 391.682 93.7241 391.612C94.5094 391.542 95.2421 391.188 95.785 390.616C97.949 392.407 100.471 390.396 100.471 390.396C103.189 391.807 105.71 389.205 105.71 389.205C107.271 389.991 107.653 388.998 107.653 388.998C112.337 388.698 105.039 373.706 105.039 373.706C103.291 360.242 106.773 352.748 106.773 352.748C118.178 318.926 118.758 309.948 114.199 297.204C112.915 293.524 112.59 292.067 113.181 290.47C114.547 286.783 113.551 271.953 115.217 266.064C118.431 254.706 121.602 225.903 123.254 212.464C125.475 194.364 115.388 170.088 115.388 170.088C113.179 160.21 116.418 125.016 116.418 125.016C120.941 132.054 120.768 144.477 120.768 144.477C120.05 157.506 131.294 177.42 131.294 177.42C136.694 185.649 138.742 193.456 138.742 194.036C138.742 196.407 138.223 202.145 138.223 202.145L138.43 207.145C138.803 209.721 139.034 212.316 139.123 214.918C138.28 227.953 140.35 225.501 140.35 225.501C142.098 225.501 144.018 215.011 144.018 215.011C144.018 217.711 143.357 225.811 144.818 228.869C146.564 232.512 147.848 228.244 147.871 227.387C148.333 210.787 149.33 215.138 149.33 215.138C150.301 228.602 151.494 231.644 153.63 230.591C155.25 229.818 153.769 214.433 153.769 214.433C156.544 223.572 158.649 225.027 158.649 225.027C163.229 228.243 160.397 219.361 159.76 217.602C156.371 208.256 156.267 205.017 156.267 205.017C160.501 213.417 163.692 213.104 163.692 213.104C167.822 211.786 160.083 199.894 155.548 194.197C153.234 191.297 150.248 187.408 149.384 185.097C147.973 181.188 146.907 168.62 146.907 168.62C146.48 153.79 142.813 147.348 142.813 147.348C136.544 137.314 135.365 118.598 135.365 118.598L135.09 87C132.89 65.445 117.01 65.29 117.01 65.29C100.957 62.9 98.723 57.714 98.723 57.714C95.323 52.821 97.266 43.44 97.266 43.44C100.087 41.145 101.175 35.053 101.175 35.053C105.859 31.461 105.63 26.205 103.466 26.262C101.73 26.308 102.123 24.87 102.123 24.87C105.052 1.208 84.046 0 84.046 0H80.836C80.836 0 59.821 1.208 62.746 24.864C62.746 24.864 63.139 26.304 61.388 26.256C59.23 26.199 59.029 31.456 63.696 35.047C63.696 35.047 64.783 41.137 67.605 43.434C67.605 43.434 69.548 52.814 66.148 57.708C66.148 57.708 63.922 62.894 47.861 65.284C47.861 65.284 31.952 65.44 29.788 86.994L29.488 118.594C29.488 118.594 28.331 137.311 22.038 147.344C22.038 147.344 18.389 153.787 17.967 168.616C17.967 168.616 16.898 181.184 15.492 185.093C14.635 187.393 11.653 191.276 9.32001 194.193C4.74601 199.878 -2.94199 211.745 1.17101 213.1C1.17101 213.1 4.37901 213.412 8.59601 205.013C8.59601 205.013 8.50901 208.229 5.12501 217.598C4.46001 219.334 1.63201 228.217 6.21301 225.024C6.21301 225.024 8.33501 223.567 11.093 214.43C11.093 214.43 9.61301 229.815 11.26 230.588C13.412 231.642 14.586 228.599 15.56 215.135C15.56 215.135 16.56 210.787 17.017 227.384C17.04 228.241 18.295 232.509 20.049 228.866C21.529 225.811 20.864 217.727 20.864 215.008C20.864 215.008 22.764 225.498 24.536 225.498C24.536 225.498 26.624 227.95 25.767 214.915C25.628 212.786 26.375 208.415 26.467 207.142L26.667 202.142C26.667 202.142 26.146 196.417 26.146 194.033C26.146 193.442 28.194 185.646 33.594 177.417C33.594 177.417 44.826 157.494 44.103 144.474C44.103 144.474 43.947 132.051 48.47 125.013C48.47 125.013 51.68 160.205 49.505 170.085C49.505 170.085 39.405 194.358 41.629 212.461C43.27 225.937 46.435 254.702 49.657 266.061C51.34 271.938 50.345 286.761 51.693 290.467C52.301 292.076 51.982 293.558 50.675 297.201C46.141 309.947 46.718 318.925 58.123 352.745C58.123 352.745 61.633 360.239 59.859 373.703C59.859 373.703 52.572 388.695 57.239 388.995C57.239 388.995 57.604 389.988 59.182 389.202C59.182 389.202 61.703 391.802 64.427 390.393C64.427 390.393 66.95 392.407 69.106 390.613C69.6451 391.185 70.3751 391.54 71.158 391.61C71.9409 391.681 72.7225 391.462 73.355 390.995C73.355 390.995 76.664 393.227 78.63 390.809C78.63 390.809 82.123 391.584 75.904 375.829C75.904 375.829 73.522 359.129 72.209 355.842C69.709 349.621 71.474 332.57 72.009 328.915C72.87 322.806 72.409 312.398 70.835 304.346C69.684 298.575 72.801 287.679 73.952 280.981C76.317 266.881 80.952 230.881 80.373 224.071L82.288 224.743C83.0863 224.756 83.8692 224.522 84.53 224.074Z" /> */}
<circle
className="body-part-circle"
cx="82"
cy="114"
r={CIRCLE_RADIUS}
id={BodyPart[BodyPart.UPPER_CHEST]}
/>
<circle
className="body-part-circle"
cx="82"

View File

@@ -0,0 +1,72 @@
import classNames from 'classnames';
import { Control, Controller } from 'react-hook-form';
export function Range({
control,
name,
values,
min,
max,
step,
// input props
...props
}: {
control: Control<any>;
name: string;
max: number;
min: number;
step: number;
values: { value: number; label: string; defaultValue?: boolean }[];
} & React.HTMLProps<HTMLInputElement>) {
return (
<Controller
control={control}
name={name}
render={({ field: { onChange, ref, name, value } }) => (
<label className="text-standard w-full text-center flex items-center flex-col">
<input
type="range"
className=" text-background-10 border-accent-background-30"
style={{
width: 'calc(88% - 0.5vw)',
}}
name={name}
ref={ref}
value={value}
onChange={onChange}
list={`${name}-datalist`}
min={min}
max={max}
step={step}
{...props}
/>
<datalist id={`${name}-datalist`} className="">
{values.map(({ value }, i) => (
<option key={i}>{value}</option>
))}
</datalist>
<div className="w-full flex flex-nowrap overflow-clip">
{Array((max - min) / step + 1)
.fill(0)
.map((_v, i) => {
const value = values.find(
({ value }) => i * step + min === value
);
return (
<span
key={i}
className={classNames(
'flex-1',
value?.defaultValue && 'text-status-success'
)}
>
{value?.label}
</span>
);
})}
</div>
</label>
)}
/>
);
}

View File

@@ -1,11 +1,27 @@
export function ArrowDownIcon() {
export function ArrowDownIcon({ size = 24 }: { size?: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
version="1.1"
width="24"
height="24"
width={size}
height={size}
viewBox="0 0 24 24"
>
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" />
</svg>
);
}
export function ArrowUpIcon({ size = 24 }: { size: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
version="1.1"
width={size}
height={size}
className="rotate-180"
viewBox="0 0 24 24"
>
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" />

View File

@@ -0,0 +1,16 @@
export function BellIcon({ width = 24 }: { width?: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
strokeWidth={1.5}
width={width}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0"
/>
</svg>
);
}

View File

@@ -1,4 +1,10 @@
export function PawIcon({ width = 24 }: { width?: number }) {
export function PawIcon({
width = 24,
transform = '',
}: {
width?: number;
transform?: string;
}) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -7,7 +13,7 @@ export function PawIcon({ width = 24 }: { width?: number }) {
viewBox="0 0 512 512"
>
<path
transform="scale(0.75, 0.75) translate(96, 96)"
transform={`${transform} scale(0.75, 0.75) translate(96, 96)`}
d="M490.39 182.75c-5.55-13.19-14.77-22.7-26.67-27.49l-.16-.06a46.46 46.46 0 00-17-3.2h-.64c-27.24.41-55.05 23.56-69.19 57.61-10.37 24.9-11.56 51.68-3.18 71.64 5.54 13.2 14.78 22.71 26.73 27.5l.13.05a46.53 46.53 0 0017 3.2c27.5 0 55.6-23.15 70-57.65 10.24-24.87 11.37-51.63 2.98-71.6zM381.55 329.61c-15.71-9.44-30.56-18.37-40.26-34.41C314.53 250.8 298.37 224 256 224s-58.57 26.8-85.39 71.2c-9.72 16.06-24.6 25-40.36 34.48-18.07 10.86-36.74 22.08-44.8 44.16a66.93 66.93 0 00-4.65 25c0 35.95 28 65.2 62.4 65.2 17.75 0 36.64-6.15 56.63-12.66 19.22-6.26 39.09-12.73 56.27-12.73s37 6.47 56.15 12.73C332.2 457.85 351 464 368.8 464c34.35 0 62.3-29.25 62.3-65.2a67 67 0 00-4.75-25c-8.06-22.1-26.74-33.33-44.8-44.19zM150 188.85c11.9 14.93 27 23.15 42.52 23.15a42.88 42.88 0 006.33-.47c32.37-4.76 52.54-44.26 45.92-90C242 102.3 234.6 84.39 224 71.11 212.12 56.21 197 48 181.49 48a42.88 42.88 0 00-6.33.47c-32.37 4.76-52.54 44.26-45.92 90 2.76 19.2 10.16 37.09 20.76 50.38zm163.16 22.68a42.88 42.88 0 006.33.47c15.53 0 30.62-8.22 42.52-23.15 10.59-13.29 17.95-31.18 20.75-50.4 6.62-45.72-13.55-85.22-45.92-90a42.88 42.88 0 00-6.33-.47C315 48 299.88 56.21 288 71.11c-10.6 13.28-18 31.19-20.76 50.44-6.62 45.72 13.55 85.22 45.92 89.98zM111.59 308.8l.14-.05c11.93-4.79 21.16-14.29 26.69-27.48 8.38-20 7.2-46.75-3.15-71.65C120.94 175.16 92.85 152 65.38 152a46.4 46.4 0 00-17 3.2l-.14.05c-11.9 4.75-21.13 14.29-26.66 27.48-8.38 20-7.2 46.75 3.15 71.65C39.06 288.84 67.15 312 94.62 312a46.4 46.4 0 0016.97-3.2z"
></path>
</svg>

View File

@@ -0,0 +1,26 @@
export function SlimeUpIcon({ width = 60 }: { width?: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
version="1.1"
viewBox="0 0 16 65.837"
>
<g transform="translate(-57.584 -23.825)">
<rect
width="13.926"
height="42.377"
x="59.526"
y="35.434"
strokeWidth="0.265"
rx="6.963"
ry="3.423"
></rect>
<path
strokeWidth="0.195"
d="M59.587 23.923c.514 0 .978.382 1.313 1.001.336.62.402 1.512.543 2.425l1.376 8.937v40.902l-1.38 8.95c-.14.917-.206 1.805-.542 2.425-.335.619-.8 1.001-1.314 1.001-1.028 0-2.14-1.59-1.856-3.427l1.38-8.949V36.286l-1.377-8.937c-.281-1.826.828-3.426 1.857-3.426z"
></path>
</g>
</svg>
);
}

View File

@@ -0,0 +1,13 @@
export function UpperChestIcon({ width = 24 }: { width?: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
x="0px"
y="0px"
width={width}
viewBox="0 0 50 50"
>
<path d="M 20 2 C 18.156 2 16.700141 3.1345312 15.619141 4.0195312 C 12.698141 4.2755313 4 7.245 4 15 C 4 17.305 4.551 19.068203 4.875 19.908203 C 4.262 20.969203 3 23.679 3 28 C 3 28.352 3.184375 28.677422 3.484375 28.857422 L 8.484375 31.857422 C 8.835375 32.068422 9.2804219 32.044922 9.6074219 31.794922 C 10.290422 31.270922 10.833578 30.512578 11.267578 29.642578 C 11.118578 28.880578 11 28.05 11 27 L 11 21 C 11 20.448 11.448 20 12 20 C 12.43 20 12.790641 20.27425 12.931641 20.65625 C 12.944641 20.68425 12.982 20.797656 13 20.847656 C 13.197 21.404656 14.365 24 19 24 C 23.133 24 23.984531 19.976687 24.019531 19.804688 C 24.113531 19.329687 24.535 19.018531 25 19.019531 C 25.465 19.019531 25.886469 19.330687 25.980469 19.804688 C 26.015469 19.976687 26.867 24 31 24 C 35.635 24 36.803 21.405656 37 20.847656 C 37.018 20.797656 37.055359 20.68425 37.068359 20.65625 C 37.209359 20.27525 37.57 20 38 20 C 38.552 20 39 20.448 39 21 L 39 27 C 39 28.05 38.881422 28.881578 38.732422 29.642578 C 39.166422 30.513578 39.709578 31.269969 40.392578 31.792969 C 40.719578 32.042969 41.164625 32.066469 41.515625 31.855469 L 46.515625 28.855469 C 46.815625 28.676469 47 28.352 47 28 C 47 23.679 45.738 20.969203 45.125 19.908203 C 45.449 19.068203 46 17.305 46 15 C 46 7.245 37.301859 4.2755312 34.380859 4.0195312 C 33.299859 3.1345312 31.844 2 30 2 L 25 2 L 20 2 z M 25 22.609375 C 23.953 24.323375 22.059 26 19 26 C 16.075 26 14.195 25.130766 13 24.134766 L 13 27 C 13 28.281 13.194875 29.155016 13.421875 30.166016 C 13.692875 31.375016 14 32.746 14 35 C 14 35.027 13.987375 35.049172 13.984375 35.076172 C 13.994375 35.366172 14 35.669 14 36 L 14 42 C 14 44.997 18.628641 47.438484 19.556641 47.896484 C 19.693641 47.965484 19.847 48 20 48 L 25 48 L 30 48 C 30.153 48 30.306359 47.965484 30.443359 47.896484 C 31.371359 47.438484 36 44.997 36 42 L 36 36 C 36 35.669 36.005625 35.366172 36.015625 35.076172 C 36.012625 35.049172 36 35.027 36 35 C 36 32.746 36.307125 31.375016 36.578125 30.166016 C 36.805125 29.155016 37 28.281 37 27 L 37 24.134766 C 35.805 25.130766 33.925 26 31 26 C 27.941 26 26.047 24.323375 25 22.609375 z"></path>
</svg>
);
}

View File

@@ -1,6 +1,11 @@
import { useLocalization } from '@fluent/react';
import { useMemo } from 'react';
import { ResetRequestT, ResetType, RpcMessage } from 'solarxr-protocol';
import {
ResetRequestT,
ResetType,
RpcMessage,
StatusData,
} from 'solarxr-protocol';
import { useConfig } from '../../hooks/config';
import { useCountdown } from '../../hooks/countdown';
import { useWebsocketAPI } from '../../hooks/websocket-api';
@@ -12,6 +17,7 @@ import {
YawResetIcon,
FullResetIcon,
} from '../commons/icon/ResetIcon';
import { useStatusContext } from '../../hooks/status-system';
export function ResetButton({
type,
@@ -24,8 +30,18 @@ export function ResetButton({
}) {
const { l10n } = useLocalization();
const { sendRPCPacket } = useWebsocketAPI();
const { statuses } = useStatusContext();
const { config } = useConfig();
const needsFullReset = useMemo(
() =>
type === ResetType.Mounting &&
Object.values(statuses).some(
(status) => status.dataType === StatusData.StatusTrackerReset
),
[statuses]
);
const reset = () => {
const req = new ResetRequestT();
req.resetType = type;
@@ -75,7 +91,7 @@ export function ResetButton({
maybePlaySoundOnResetStarted(type);
}}
variant="primary"
disabled={isCounting}
disabled={isCounting || needsFullReset}
>
<div className="relative">
<div className="opacity-0 h-0">{text}</div>
@@ -91,7 +107,7 @@ export function ResetButton({
startCountdown();
maybePlaySoundOnResetStarted(type);
}}
disabled={isCounting}
disabled={isCounting || needsFullReset}
></BigButton>
),
};

View File

@@ -6,7 +6,12 @@ import { BodyInteractions } from '../commons/BodyInteractions';
import { TrackerPartCard } from '../tracker/TrackerPartCard';
import { BodyPartError } from './pages/trackers-assign/TrackerAssignment';
export const SPINE_PARTS = [BodyPart.HIP, BodyPart.CHEST, BodyPart.WAIST];
export const SPINE_PARTS = [
BodyPart.UPPER_CHEST,
BodyPart.CHEST,
BodyPart.WAIST,
BodyPart.HIP,
];
export const ASSIGNMENT_RULES: Partial<
Record<BodyPart, (BodyPart | BodyPart[])[]>
> = {
@@ -26,6 +31,8 @@ export const ASSIGNMENT_RULES: Partial<
[BodyPart.RIGHT_UPPER_LEG]: [SPINE_PARTS],
[BodyPart.HIP]: [BodyPart.CHEST],
[BodyPart.WAIST]: [BodyPart.CHEST],
// TODO chest OR upperChest.
// Also don't warn if no legs.
};
export function BodyAssignment({
@@ -177,6 +184,17 @@ export function BodyAssignment({
}
rightControls={
<div className="flex flex-col justify-between h-full">
{advanced && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.UPPER_CHEST]?.label}
td={trackerPartGrouped[BodyPart.UPPER_CHEST]}
role={BodyPart.UPPER_CHEST}
onClick={() => onRoleSelected(BodyPart.UPPER_CHEST)}
direction="left"
/>
)}
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.CHEST]?.label}
@@ -275,6 +293,19 @@ export function BodyAssignment({
direction="left"
/>
</div>
{advanced && (
<div className="flex flex-col gap-2">
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.ACCESSORY]?.label}
td={trackerPartGrouped[BodyPart.ACCESSORY]}
role={BodyPart.ACCESSORY}
onClick={() => onRoleSelected(BodyPart.ACCESSORY)}
direction="left"
/>
</div>
)}
</div>
}
></BodyInteractions>

View File

@@ -1,24 +1,39 @@
import { ReactNode } from 'react';
import { ReactNode, useState } from 'react';
import { useLayout } from '../../hooks/layout';
import { useOnboarding } from '../../hooks/onboarding';
import { MainLayoutRoute } from '../MainLayout';
import { TopBar } from '../TopBar';
import { useBreakpoint } from '../../hooks/breakpoint';
import { SkipSetupButton } from './SkipSetupButton';
import { SkipSetupWarningModal } from './SkipSetupWarningModal';
export function OnboardingLayout({ children }: { children: ReactNode }) {
const { layoutHeight, ref } = useLayout<HTMLDivElement>();
const { isMobile } = useBreakpoint('mobile');
const { state } = useOnboarding();
const { state, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
return !state.alonePage ? (
<>
<TopBar progress={state.progress}></TopBar>
<div
ref={ref}
className="flex-grow xs:pt-10 mobile:pt-2"
className="flex-grow relative"
style={{ height: layoutHeight }}
>
<div className="absolute top-12 mobile:top-0 right-2 z-50">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
</div>
{children}
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
</>
) : (

View File

@@ -3,8 +3,6 @@ import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { Typography } from '../../commons/Typography';
import { useMemo, useState } from 'react';
import { SkipSetupWarningModal } from '../SkipSetupWarningModal';
import { SkipSetupButton } from '../SkipSetupButton';
import { ProgressBar } from '../../commons/ProgressBar';
import { LoaderIcon, SlimeState } from '../../commons/icon/LoaderIcon';
import { useCountdown } from '../../../hooks/countdown';
@@ -22,8 +20,7 @@ export const IMU_CALIBRATION_TIME = 4;
export function CalibrationTutorialPage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { applyProgress } = useOnboarding();
const [calibrationStatus, setCalibrationStatus] = useState(
CalibrationStatus.WAITING
);
@@ -72,11 +69,6 @@ export function CalibrationTutorialPage() {
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex w-full h-full justify-center xs:px-20 mobile:px-5 pb-5 gap-14">
<div className="flex gap-4 self-center mobile:z-10">
<div className="flex flex-col max-w-md gap-3">
@@ -160,11 +152,6 @@ export function CalibrationTutorialPage() {
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
</>
);

View File

@@ -20,8 +20,6 @@ import { ProgressBar } from '../../commons/ProgressBar';
import { TipBox } from '../../commons/TipBox';
import { Typography } from '../../commons/Typography';
import { TrackerCard } from '../../tracker/TrackerCard';
import { SkipSetupWarningModal } from '../SkipSetupWarningModal';
import { SkipSetupButton } from '../SkipSetupButton';
import { useBnoExists } from '../../../hooks/imu-logic';
import { useBreakpoint } from '../../../hooks/breakpoint';
@@ -60,22 +58,19 @@ const statusProgressMap = {
export function ConnectTrackersPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { layoutHeight, ref } = isMobile
? { layoutHeight: 0, ref: undefined }
: useLayout<HTMLDivElement>();
const { useConnectedTrackers } = useTrackers();
const { applyProgress, state, skipSetup } = useOnboarding();
const { layoutHeight, ref } = useLayout<HTMLDivElement>();
const { useConnectedIMUTrackers } = useTrackers();
const { applyProgress, state } = useOnboarding();
const navigate = useNavigate();
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
const [provisioningStatus, setProvisioningStatus] =
useState<WifiProvisioningStatus>(WifiProvisioningStatus.NONE);
const [skipWarning, setSkipWarning] = useState(false);
applyProgress(0.4);
const connectedTrackers = useConnectedTrackers();
const connectedIMUTrackers = useConnectedIMUTrackers();
const bnoExists = useBnoExists(connectedTrackers);
const bnoExists = useBnoExists(connectedIMUTrackers);
useEffect(() => {
if (!state.wifi) {
@@ -132,14 +127,9 @@ export function ConnectTrackersPage() {
}, [provisioningStatus]);
return (
<div className="flex flex-col h-full items-center relative overflow-y-auto px-4 pb-4">
<SkipSetupButton
visible={!state.alonePage}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col h-full items-center px-4 pb-4">
<div className="flex gap-10 mobile:flex-col w-full xs:max-w-7xl">
<div className="flex flex-col w-full max-w-sm">
<div className="flex flex-col w-full xs:max-w-sm">
<Typography variant="main-title">
{l10n.getString('onboarding-connect_tracker-title')}
</Typography>
@@ -232,25 +222,29 @@ export function ConnectTrackersPage() {
<div className="flex flex-col xs:flex-grow">
<Typography color="secondary" bold>
{l10n.getString('onboarding-connect_tracker-connected_trackers', {
amount: connectedTrackers.length,
amount: connectedIMUTrackers.length,
})}
</Typography>
<div
className="xs:flex-grow xs:overflow-y-scroll"
className="overflow-y-scroll mt-2"
ref={ref}
style={isMobile ? { height: layoutHeight - BOTTOM_HEIGHT } : {}}
style={
isMobile && state.alonePage
? { height: layoutHeight - BOTTOM_HEIGHT }
: { height: layoutHeight }
}
>
<div className="grid lg:grid-cols-2 md:grid-cols-1 gap-2 xs:mx-3 pt-3">
<div className="grid lg:grid-cols-2 md:grid-cols-1 gap-2 pr-1">
{Array.from({
...connectedTrackers,
length: Math.max(connectedTrackers.length, isMobile ? 1 : 20),
...connectedIMUTrackers,
length: Math.max(connectedIMUTrackers.length, 1),
}).map((tracker, index) => (
<div key={index}>
{!tracker && (
<div
className={classNames(
'rounded-xl h-16 mobile:animate-pulse',
'rounded-xl h-16 animate-pulse',
state.alonePage
? 'bg-background-80'
: 'bg-background-70'
@@ -270,11 +264,6 @@ export function ConnectTrackersPage() {
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
);
}

View File

@@ -1,28 +1,19 @@
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { SlimeVRIcon } from '../../commons/icon/SimevrIcon';
import { LangSelector } from '../../commons/LangSelector';
import { Typography } from '../../commons/Typography';
import { SkipSetupButton } from '../SkipSetupButton';
import { SkipSetupWarningModal } from '../SkipSetupWarningModal';
export function HomePage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { applyProgress } = useOnboarding();
applyProgress(0.1);
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative px-4">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center px-4">
<div className="flex flex-col gap-5 items-center z-10 scale-150 mb-20">
<SlimeVRIcon></SlimeVRIcon>
<Typography variant="mobile-title">
@@ -45,7 +36,7 @@ export function HomePage() {
></div>
<img
className="absolute"
src="/images/slime-girl.png"
src="/images/slime-girl.webp"
style={{
width: '35%',
maxWidth: 800,
@@ -55,7 +46,7 @@ export function HomePage() {
/>
<img
className="absolute"
src="/images/slimes.png"
src="/images/slimes.webp"
style={{
width: '35%',
maxWidth: 800,
@@ -64,11 +55,6 @@ export function HomePage() {
}}
/>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</>
);
}

View File

@@ -3,8 +3,6 @@ import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { Typography } from '../../commons/Typography';
import { useState, useMemo, useEffect } from 'react';
import { SkipSetupWarningModal } from '../SkipSetupWarningModal';
import { SkipSetupButton } from '../SkipSetupButton';
import {
BodyPart,
ResetResponseT,
@@ -19,12 +17,12 @@ import { BodyDisplay } from '../../commons/BodyDisplay';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import classNames from 'classnames';
import { useBreakpoint } from '../../../hooks/breakpoint';
import { log } from '../../../utils/logging';
export function ResetTutorialPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { applyProgress, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { applyProgress } = useOnboarding();
const { useAssignedTrackers } = useTrackers();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [curIndex, setCurIndex] = useState(0);
@@ -85,7 +83,7 @@ export function ResetTutorialPage() {
RpcMessage.ResetResponse,
({ status, resetType }: ResetResponseT) => {
if (status !== ResetStatus.STARTED) return;
console.log(status);
log(status);
if (resetType === RESET_TYPE_ORDER[curIndex]) {
setCurIndex(curIndex + 1);
}
@@ -122,18 +120,13 @@ export function ResetTutorialPage() {
return (
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center relative overflow-y-auto">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex xs:flex-row mobile:flex-col w-full h-full xs:justify-center xs:px-20 mobile:px-4 gap-8 self-center">
<div className="flex flex-col gap-3 xs:w-96 self-center">
<Typography variant="main-title">
{l10n.getString('onboarding-reset_tutorial')}
</Typography>
<Typography color="secondary">
{l10n.getString('onboarding-reset_tutorial-description')}
{l10n.getString('onboarding-reset_tutorial-explanation')}
</Typography>
<div className="flex">
<Button variant="secondary" to="/onboarding/mounting/choose">
@@ -197,16 +190,16 @@ export function ResetTutorialPage() {
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
);
}
export const TORSO_PARTS = [BodyPart.CHEST, BodyPart.WAIST, BodyPart.HIP];
export const TORSO_PARTS = [
BodyPart.UPPER_CHEST,
BodyPart.CHEST,
BodyPart.WAIST,
BodyPart.HIP,
];
export const LEFT_LEG_PARTS = [
BodyPart.LEFT_UPPER_LEG,
BodyPart.LEFT_LOWER_LEG,

View File

@@ -4,24 +4,20 @@ import { useWifiForm } from '../../../hooks/wifi-form';
import { Button } from '../../commons/Button';
import { Input } from '../../commons/Input';
import { Typography } from '../../commons/Typography';
import { useState } from 'react';
import { SkipSetupWarningModal } from '../SkipSetupWarningModal';
import { SkipSetupButton } from '../SkipSetupButton';
import classNames from 'classnames';
import { useTrackers } from '../../../hooks/tracker';
import { useBnoExists } from '../../../hooks/imu-logic';
export function WifiCredsPage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const { applyProgress, state } = useOnboarding();
const { control, handleSubmit, submitWifiCreds, formState } = useWifiForm();
const { useConnectedTrackers } = useTrackers();
const [skipWarning, setSkipWarning] = useState(false);
const connectedTrackers = useConnectedTrackers();
const { useConnectedIMUTrackers } = useTrackers();
const connectedIMUTrackers = useConnectedIMUTrackers();
applyProgress(0.2);
const bnoExists = useBnoExists(connectedTrackers);
const bnoExists = useBnoExists(connectedIMUTrackers);
return (
<form
@@ -29,11 +25,6 @@ export function WifiCredsPage() {
onSubmit={handleSubmit(submitWifiCreds)}
>
<div className="flex flex-col w-full h-full xs:justify-center items-center relative ">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex mobile:flex-col xs:gap-10 px-4">
<div className="flex flex-col max-w-sm">
<Typography variant="main-title">
@@ -117,11 +108,6 @@ export function WifiCredsPage() {
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</form>
);
}

View File

@@ -2,9 +2,6 @@ import { useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../../hooks/onboarding';
import { Button } from '../../../commons/Button';
import { Typography } from '../../../commons/Typography';
import { useState } from 'react';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupButton } from '../../SkipSetupButton';
import { useTrackers } from '../../../../hooks/tracker';
import { useBnoExists } from '../../../../hooks/imu-logic';
import { StickerSlime } from './StickerSlime';
@@ -13,93 +10,80 @@ import { ExtensionArrow } from './ExtensionArrow';
export function AssignmentTutorialPage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { useConnectedTrackers } = useTrackers();
const connectedTrackers = useConnectedTrackers();
const bnoExists = useBnoExists(connectedTrackers);
const { applyProgress } = useOnboarding();
const { useConnectedIMUTrackers } = useTrackers();
const connectedIMUTrackers = useConnectedIMUTrackers();
const bnoExists = useBnoExists(connectedIMUTrackers);
applyProgress(0.46);
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col w-full h-full justify-center xs:px-20 gap-3 pb-2">
<div className="overflow-y-auto px-4">
<div className="mb-10 self-center">
<Typography variant="main-title">
{l10n.getString('onboarding-assignment_tutorial')}
</Typography>
<div className="flex flex-col gap-5 h-full items-center overflow-y-auto w-full xs:justify-center relative py-2">
<div className="flex flex-col w-full xs:justify-center xs:px-20 gap-3 pb-2 px-4">
<div className="mb-10 self-center">
<Typography variant="main-title">
{l10n.getString('onboarding-assignment_tutorial')}
</Typography>
</div>
<div className="flex flex-col self-center justify-center gap-5 px-2">
<div className="flex gap-12 xs:flex-row mobile:flex-col self-center justify-center">
<div className="flex flex-col gap-5 xs:w-1/4">
<div>
<Typography variant="section-title">
{l10n.getString(
'onboarding-assignment_tutorial-first_step'
)}
</Typography>
</div>
<div className="stroke-background-10 fill-background-10 flex justify-center">
<StickerSlime width="65%"></StickerSlime>
</div>
</div>
<div className="flex flex-col gap-10 xs:w-1/4">
<div>
<Typography variant="section-title">
{l10n.getString(
'onboarding-assignment_tutorial-second_step'
)}
</Typography>
</div>
<div className="fill-background-10 stroke-background-10 flex justify-center">
<TrackerArrow width="75%"></TrackerArrow>
</div>
<div>
<Typography variant="section-title">
{l10n.getString(
'onboarding-assignment_tutorial-second_step-continuation'
)}
</Typography>
</div>
<div className="fill-background-10 stroke-background-10 flex justify-center">
<ExtensionArrow width="75%"></ExtensionArrow>
</div>
</div>
</div>
<div className="flex flex-col self-center justify-center gap-5 px-2">
<div className="flex gap-12 xs:flex-row mobile:flex-col self-center justify-center">
<div className="flex flex-col gap-5 xs:w-1/4">
<div>
<Typography variant="section-title">
{l10n.getString(
'onboarding-assignment_tutorial-first_step'
)}
</Typography>
</div>
<div className="stroke-background-10 fill-background-10 flex justify-center">
<StickerSlime width="65%"></StickerSlime>
</div>
</div>
<div className="flex flex-col gap-10 xs:w-1/4">
<div>
<Typography variant="section-title">
{l10n.getString(
'onboarding-assignment_tutorial-second_step'
)}
</Typography>
</div>
<div className="fill-background-10 stroke-background-10 flex justify-center">
<TrackerArrow width="75%"></TrackerArrow>
</div>
<div>
<Typography variant="section-title">
{l10n.getString(
'onboarding-assignment_tutorial-second_step-continuation'
)}
</Typography>
</div>
<div className="fill-background-10 stroke-background-10 flex justify-center">
<ExtensionArrow width="75%"></ExtensionArrow>
</div>
</div>
</div>
<div className="flex">
<Button
variant="secondary"
to={
bnoExists
? '/onboarding/calibration-tutorial'
: '/onboarding/wifi-creds'
}
>
{l10n.getString('onboarding-previous_step')}
</Button>
<Button
variant="primary"
to="/onboarding/trackers-assign"
className="ml-auto"
>
{l10n.getString('onboarding-assignment_tutorial-done')}
</Button>
</div>
<div className="flex">
<Button
variant="secondary"
to={
bnoExists
? '/onboarding/calibration-tutorial'
: '/onboarding/wifi-creds'
}
>
{l10n.getString('onboarding-previous_step')}
</Button>
<Button
variant="primary"
to="/onboarding/trackers-assign"
className="ml-auto"
>
{l10n.getString('onboarding-assignment_tutorial-done')}
</Button>
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
</>
);

View File

@@ -1,5 +1,4 @@
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { RpcMessage, SkeletonResetAllRequestT } from 'solarxr-protocol';
import {
AutoboneContextC,
@@ -16,16 +15,14 @@ import { PutTrackersOnStep } from './autobone-steps/PutTrackersOn';
import { Recording } from './autobone-steps/Recording';
import { StartRecording } from './autobone-steps/StartRecording';
import { VerifyResultsStep } from './autobone-steps/VerifyResults';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupButton } from '../../SkipSetupButton';
import { useCountdown } from '../../../../hooks/countdown';
import { CheckHeight } from './autobone-steps/СheckHeight';
export function AutomaticProportionsPage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const { applyProgress, state } = useOnboarding();
const { sendRPCPacket } = useWebsocketAPI();
const context = useProvideAutobone();
const [skipWarning, setSkipWarning] = useState(false);
const { isCounting, startCountdown, timer } = useCountdown({
onCountdownEnd: () => {
sendRPCPacket(
@@ -39,13 +36,8 @@ export function AutomaticProportionsPage() {
return (
<AutoboneContextC.Provider value={context}>
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center relative px-4 pb-4">
<SkipSetupButton
visible={!state.alonePage}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col w-full h-full justify-center max-w-3xl gap-5">
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center overflow-y-auto overflow-x-hidden relative px-4 pb-4">
<div className="flex flex-col w-full xs:h-full xs:justify-center max-w-3xl gap-5">
<div className="flex flex-col max-w-lg gap-3">
<Typography variant="main-title">
{l10n.getString('onboarding-automatic_proportions-title')}
@@ -62,6 +54,7 @@ export function AutomaticProportionsPage() {
steps={[
{ type: 'numbered', component: PutTrackersOnStep },
{ type: 'numbered', component: RequirementsStep },
{ type: 'numbered', component: CheckHeight },
{ type: 'numbered', component: StartRecording },
{ type: 'fullsize', component: Recording },
{ type: 'numbered', component: VerifyResultsStep },
@@ -85,11 +78,6 @@ export function AutomaticProportionsPage() {
</Button>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</AutoboneContextC.Provider>
);
}

View File

@@ -1,6 +1,13 @@
import { useLocalization } from '@fluent/react';
import classNames from 'classnames';
import { MouseEventHandler, ReactNode, useEffect } from 'react';
import {
MouseEventHandler,
ReactNode,
useEffect,
useRef,
UIEvent,
useMemo,
} from 'react';
import {
LabelType,
ProportionChangeType,
@@ -8,7 +15,9 @@ import {
} from '../../../../hooks/manual-proportions';
import { useLocaleConfig } from '../../../../i18n/config';
import { Typography } from '../../../commons/Typography';
import { ArrowDownIcon, ArrowUpIcon } from '../../../commons/icon/ArrowIcons';
import { useBreakpoint } from '../../../../hooks/breakpoint';
import { debounce } from '../../../../hooks/timeout';
function IncrementButton({
children,
@@ -21,7 +30,8 @@ function IncrementButton({
<div
onClick={onClick}
className={classNames(
'p-3 rounded-lg xs:w-16 xs:h-16 mobile:w-10 flex flex-col justify-center items-center bg-background-60 hover:bg-opacity-50'
'p-3 rounded-lg xs:w-16 xs:h-16 mobile:w-10 flex flex-col justify-center items-center',
'bg-background-60 hover:bg-opacity-50 active:bg-accent-background-30'
)}
>
<Typography variant="mobile-title" bold>
@@ -40,23 +50,29 @@ export function BodyProportions({
type: 'linear' | 'ratio';
variant: 'onboarding' | 'alone';
}) {
const { isMobile } = useBreakpoint('mobile');
const [bodyParts, _ratioMode, currentSelection, dispatch, setRatioMode] =
useManualProportions();
const { currentLocales } = useLocaleConfig();
const { bodyParts, dispatch, state, setRatioMode } = useManualProportions();
const { l10n } = useLocalization();
const { currentLocales } = useLocaleConfig();
const { isTall } = useBreakpoint('tall');
const offsetItems = isTall ? 2 : 1;
const itemsToDisplay = offsetItems * 2 + 1;
const itemHeight = 80;
const scrollHeight = itemHeight * itemsToDisplay;
const scrollerRef = useRef<HTMLDivElement | null>(null);
const cmFormat = Intl.NumberFormat(currentLocales, {
style: 'unit',
unit: 'centimeter',
maximumFractionDigits: 1,
});
const configFormat = Intl.NumberFormat(currentLocales, {
signDisplay: 'always',
const percentageFormat = new Intl.NumberFormat(currentLocales, {
style: 'percent',
maximumFractionDigits: 1,
});
const percentageFormat = Intl.NumberFormat(currentLocales, {
style: 'percent',
const configFormat = Intl.NumberFormat(currentLocales, {
signDisplay: 'always',
maximumFractionDigits: 1,
});
@@ -68,131 +84,240 @@ export function BodyProportions({
}
}, [type]);
useEffect(() => {
if (scrollerRef.current && bodyParts.length > 0) {
selectId(bodyParts[offsetItems].label);
}
}, [scrollerRef, bodyParts.length]);
const handleUIEvent = (e: UIEvent<HTMLDivElement>) => {
const target = e.target as HTMLDivElement;
const itemHeight = target.offsetHeight / itemsToDisplay;
const atSnappingPoint = target.scrollTop % itemHeight === 0;
const index = Math.round(target.scrollTop / itemHeight);
const elem = scrollerRef.current?.childNodes[
index + offsetItems
] as HTMLDivElement;
elem.scrollIntoView({ behavior: 'smooth', block: 'center' });
if (atSnappingPoint) {
const elem = scrollerRef.current?.childNodes[
index + offsetItems
] as HTMLDivElement;
const id = elem.getAttribute('itemid');
if (id) selectNew(id);
}
};
const moveToId = (id: string) => {
if (!scrollerRef.current) return;
const index = bodyParts.findIndex(({ label }) => label === id);
scrollerRef.current.scrollTo({
top: index * itemHeight,
behavior: 'smooth',
});
};
const clickPart = (id: string) => () => {
moveToId(id);
selectNew(id);
};
const selectId = (id: string) => {
moveToId(id);
if (id) selectNew(id);
};
const selectNew = (id: string) => {
const part = bodyParts.find(({ label }) => label === id);
if (!part) return;
const { value: originalValue, label, type, ...props } = part;
const value =
'index' in props && props.index !== undefined
? props.bones[props.index].value
: originalValue;
switch (type) {
case LabelType.Bone: {
if (!('bone' in props)) throw 'unreachable';
dispatch({
...props,
label,
value,
type: ProportionChangeType.Bone,
});
break;
}
case LabelType.Group: {
if (!('bones' in props)) throw 'unreachable';
dispatch({
...props,
label,
value,
type: ProportionChangeType.Group,
index: undefined,
parentLabel: label,
});
break;
}
case LabelType.GroupPart: {
if (!('index' in props)) throw 'unreachable';
dispatch({
...props,
label,
// If this isn't done, we are replacing total
// with percentage value
value: originalValue,
type: ProportionChangeType.Group,
index: props.index,
});
}
}
};
const seletedLabel = useMemo(() => {
return bodyParts.find(({ label }) => label === state.currentLabel);
}, [state]);
const move = (action: 'next' | 'prev') => {
const elem = scrollerRef.current?.querySelector(
`div[itemid=${state.currentLabel}]`
);
const moveId = (id: string) => {
moveToId(id);
selectNew(id);
};
if (action === 'prev') {
const prevElem = elem?.previousSibling as HTMLDivElement;
const prevId = prevElem.getAttribute('itemid');
if (!prevId) return;
moveId(prevId);
}
if (action === 'next') {
const nextElem = elem?.nextSibling as HTMLDivElement;
const nextId = nextElem.getAttribute('itemid');
if (!nextId) return;
moveId(nextId);
}
};
return (
<div className="relative w-full">
<div
className={classNames(
'flex flex-col xs:overflow-y-scroll xs:overflow-x-hidden xs:max-h-[450px] xs:h-[54vh]',
'w-full px-1 gap-3 xs:gradient-mask-b-90'
)}
>
<>
{bodyParts.map(({ label, type, value: originalValue, ...props }) => {
const value =
'index' in props && props.index !== undefined
? props.bones[props.index].value
: originalValue;
const selected = isMobile || currentSelection.label === label;
const selectNew = () => {
switch (type) {
case LabelType.Bone: {
if (!('bone' in props)) throw 'unreachable';
dispatch({
...props,
label,
value,
type: ProportionChangeType.Bone,
});
break;
}
case LabelType.Group: {
if (!('bones' in props)) throw 'unreachable';
dispatch({
...props,
label,
value,
type: ProportionChangeType.Group,
index: undefined,
parentLabel: label,
});
break;
}
case LabelType.GroupPart: {
if (!('index' in props)) throw 'unreachable';
dispatch({
...props,
label,
// If this isn't done, we are replacing total
// with percentage value
value: originalValue,
type: ProportionChangeType.Group,
index: props.index,
});
(bodyParts.length > 0 && (
<div className="flex w-full gap-3">
<div className="flex items-center mobile:justify-center mobile:flex-col gap-2 my-2">
{!precise && (
<div className="mobile:order-2">
<IncrementButton
onClick={() =>
seletedLabel?.type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.05,
})
: dispatch({
type: ProportionChangeType.Linear,
value: -5,
})
}
>
{configFormat.format(-5)}
</IncrementButton>
</div>
)}
<div className="mobile:order-1">
<IncrementButton
onClick={() =>
seletedLabel?.type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.01,
})
: dispatch({
type: ProportionChangeType.Linear,
value: -1,
})
}
};
>
{configFormat.format(-1)}
</IncrementButton>
</div>
{precise && (
<div className="mobile:order-2">
<IncrementButton
onClick={() =>
seletedLabel?.type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.005,
})
: dispatch({
type: ProportionChangeType.Linear,
value: -0.5,
})
}
>
{configFormat.format(-0.5)}
</IncrementButton>
</div>
)}
</div>
<div className="flex flex-grow flex-col">
<div className="flex justify-center">
<div
onClick={() => move('prev')}
className={classNames(
'h-12 w-32 rounded-lg bg-background-60 flex flex-col justify-center',
'items-center fill-background-10',
scrollerRef?.current?.scrollTop ?? 0 > 0
? 'opacity-100 active:bg-accent-background-30'
: 'opacity-50'
)}
>
<ArrowUpIcon size={32}></ArrowUpIcon>
</div>
</div>
<div
ref={scrollerRef}
onScroll={debounce(handleUIEvent, 150)} // Debounce at 150ms to match the animation speed and prevent snaping between two animations
className={classNames(
'flex-grow flex-col overflow-y-auto',
'no-scrollbar'
)}
style={{ height: scrollHeight }}
>
{Array.from({ length: offsetItems }).map((_, index) => (
<div style={{ height: itemHeight }} key={index}></div>
))}
{bodyParts.map((part) => {
const { label, value: originalValue, type, ...props } = part;
const value =
'index' in props && props.index !== undefined
? props.bones[props.index].value
: originalValue;
return (
<div className="flex" key={label}>
const selected = state.currentLabel === label;
return (
<div
className={classNames(
'flex gap-2 transition-opacity duration-300',
!selected && 'opacity-0 pointer-events-none'
)}
>
{!precise && (
<IncrementButton
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.05,
})
: dispatch({
type: ProportionChangeType.Linear,
value: -5,
});
}}
>
{configFormat.format(-5)}
</IncrementButton>
)}
<IncrementButton
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.01,
})
: dispatch({
type: ProportionChangeType.Linear,
value: -1,
});
}}
>
{configFormat.format(-1)}
</IncrementButton>
{precise && (
<IncrementButton
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.005,
})
: dispatch({
type: ProportionChangeType.Linear,
value: -0.5,
});
}}
>
{configFormat.format(-0.5)}
</IncrementButton>
)}
</div>
<div
className="flex flex-grow flex-col px-2"
onClick={selectNew}
key={label}
itemID={label}
onClick={clickPart(label)}
style={{ height: itemHeight }}
className="flex-col flex justify-center"
>
<div
key={label}
className={classNames(
'p-3 rounded-lg xs:h-16 flex w-full items-center justify-between xs:px-6 mobile:px-3 transition-colors duration-300 bg-background-60',
(selected && 'opacity-100') || 'opacity-50'
'h-16 p-3 rounded-lg flex w-full items-center justify-between px-6 transition-colors',
'duration-300 bg-background-60',
(selected && 'opacity-100') ||
'opacity-50 active:bg-accent-background-30'
)}
>
<Typography variant="section-title" bold>
@@ -211,70 +336,93 @@ export function BodyProportions({
</Typography>
</div>
</div>
<div
className={classNames(
'flex gap-2 transition-opacity duration-300',
!selected && 'opacity-0 pointer-events-none'
)}
>
{precise && (
<IncrementButton
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.005,
})
: dispatch({
type: ProportionChangeType.Linear,
value: 0.5,
});
}}
>
{configFormat.format(+0.5)}
</IncrementButton>
)}
<IncrementButton
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.01,
})
: dispatch({
type: ProportionChangeType.Linear,
value: 1,
});
}}
>
{configFormat.format(+1)}
</IncrementButton>
{!precise && (
<IncrementButton
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.05,
})
: dispatch({
type: ProportionChangeType.Linear,
value: 5,
});
}}
>
{configFormat.format(+5)}
</IncrementButton>
)}
</div>
</div>
);
})}
</>
);
})}
{Array.from({ length: offsetItems }).map((_, index) => (
<div
className="h-20"
style={{ height: itemHeight }}
key={index}
></div>
))}
</div>
<div className="flex justify-center">
<div
onClick={() => move('next')}
className={classNames(
'h-12 w-32 rounded-lg bg-background-60 flex flex-col justify-center',
'items-center fill-background-10',
scrollerRef?.current?.scrollTop !==
(scrollerRef?.current?.scrollHeight ?? 0) -
(scrollerRef?.current?.offsetHeight ?? 0)
? 'opacity-100 active:bg-accent-background-30'
: 'opacity-50'
)}
>
<ArrowDownIcon size={32}></ArrowDownIcon>
</div>
</div>
</div>
<div className="flex items-center mobile:justify-center mobile:flex-col gap-2">
{precise && (
<div className="mobile:order-2">
<IncrementButton
onClick={() =>
seletedLabel?.type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.005,
})
: dispatch({
type: ProportionChangeType.Linear,
value: 0.5,
})
}
>
{configFormat.format(+0.5)}
</IncrementButton>
</div>
)}
<div className="mobile:order-1">
<IncrementButton
onClick={() =>
seletedLabel?.type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.01,
})
: dispatch({
type: ProportionChangeType.Linear,
value: 1,
})
}
>
{configFormat.format(+1)}
</IncrementButton>
</div>
{!precise && (
<div className="mobile:order-2">
<IncrementButton
onClick={() =>
seletedLabel?.type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.05,
})
: dispatch({
type: ProportionChangeType.Linear,
value: 5,
})
}
>
{configFormat.format(+5)}
</IncrementButton>
</div>
)}
</div>
</div>
</div>
)) || <></>
);
}

View File

@@ -8,9 +8,7 @@ import { PersonFrontIcon } from '../../../commons/PersonFrontIcon';
import { Typography } from '../../../commons/Typography';
import { BodyProportions } from './BodyProportions';
import { useLocalization } from '@fluent/react';
import { useEffect, useMemo, useState } from 'react';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupButton } from '../../SkipSetupButton';
import { useEffect, useMemo } from 'react';
import { useBreakpoint } from '../../../../hooks/breakpoint';
export function ButtonsControl() {
@@ -49,8 +47,7 @@ export function ButtonsControl() {
export function ManualProportionsPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { applyProgress, state } = useOnboarding();
applyProgress(0.9);
@@ -68,14 +65,9 @@ export function ManualProportionsPage() {
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center overflow-y-auto relative">
<SkipSetupButton
visible={!state.alonePage}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col w-full h-full xs:max-w-5xl xs:justify-center">
<div className="flex gap-8 justify-center">
<div className="flex flex-col w-full xs:max-w-2xl gap-3 items-center">
<div className="flex gap-8 justify-center h-full xs:items-center">
<div className="flex flex-col w-full xs:max-w-2xl gap-3 items-center mobile:justify-around">
<div className="flex flex-col">
<Typography variant="main-title">
{l10n.getString('onboarding-manual_proportions-title')}
@@ -100,29 +92,25 @@ export function ManualProportionsPage() {
</div>
)}
</div>
<BodyProportions
precise={precise}
type={ratio ? 'ratio' : 'linear'}
variant={state.alonePage ? 'alone' : 'onboarding'}
></BodyProportions>
<div className="w-full px-2">
<BodyProportions
precise={precise}
type={ratio ? 'ratio' : 'linear'}
variant={state.alonePage ? 'alone' : 'onboarding'}
></BodyProportions>
</div>
</div>
<div className="flex-col flex-grow gap-3 rounded-xl fill-background-50 items-center hidden md:flex">
<PersonFrontIcon width={200}></PersonFrontIcon>
</div>
</div>
{!isMobile && (
<div className="flex gap-3 mt-5 mx-4">
<div className="flex gap-3 my-5 mx-4 justify-between">
<ButtonsControl></ButtonsControl>
</div>
)}
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</>
);
}

View File

@@ -1,8 +1,6 @@
import { useOnboarding } from '../../../../hooks/onboarding';
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupButton } from '../../SkipSetupButton';
import { Localized, useLocalization } from '@fluent/react';
import { useMemo, useState } from 'react';
import classNames from 'classnames';
import { Typography } from '../../../commons/Typography';
import { Button } from '../../../commons/Button';
@@ -16,14 +14,39 @@ import saveAs from 'file-saver';
import { save } from '@tauri-apps/api/dialog';
import { writeTextFile } from '@tauri-apps/api/fs';
import { useIsTauri } from '../../../../hooks/breakpoint';
import { useAppContext } from '../../../../hooks/app';
import { error } from '../../../../utils/logging';
export const MIN_HEIGHT = 0.4;
export const MAX_HEIGHT = 4;
export const DEFAULT_HEIGHT = 1.5;
export function ProportionsChoose() {
const isTauri = useIsTauri();
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { applyProgress, state } = useOnboarding();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [animated, setAnimated] = useState(false);
const { computedTrackers } = useAppContext();
const hmdTracker = useMemo(
() =>
computedTrackers.find(
(tracker) =>
tracker.tracker.trackerId?.trackerNum === 1 &&
tracker.tracker.trackerId.deviceId?.id === undefined
),
[computedTrackers]
);
const beneathFloor = useMemo(
() =>
!(
hmdTracker?.tracker.position &&
hmdTracker.tracker.position.y >= MIN_HEIGHT
),
[hmdTracker?.tracker.position?.y]
);
useRPCPacket(
RpcMessage.SkeletonConfigResponse,
@@ -45,7 +68,7 @@ export function ProportionsChoose() {
path ? writeTextFile(path, JSON.stringify(data)) : undefined
)
.catch((err) => {
console.error(err);
error(err);
});
} else {
saveAs(blob, 'body-proportions.json');
@@ -58,11 +81,6 @@ export function ProportionsChoose() {
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center mobile:overflow-y-auto relative px-4 pb-4">
<SkipSetupButton
visible={!state.alonePage}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col gap-4 justify-center">
<Typography variant="main-title">
{l10n.getString('onboarding-choose_proportions')}
@@ -133,7 +151,7 @@ export function ProportionsChoose() {
<img
onMouseEnter={() => setAnimated(() => true)}
onAnimationEnd={() => setAnimated(() => false)}
src="/images/slimetower.png"
src="/images/slimetower.webp"
className={classNames(
'absolute w-[100px] -right-2 -top-24',
animated && 'animate-[bounce_1s_1]'
@@ -152,15 +170,23 @@ export function ProportionsChoose() {
</Typography>
</div>
<div>
<Typography color="secondary">
{l10n.getString(
'onboarding-choose_proportions-auto_proportions-description'
)}
</Typography>
<Localized
id="onboarding-choose_proportions-auto_proportions-descriptionv2"
elems={{ b: <b></b> }}
>
<Typography
color="secondary"
whitespace="whitespace-pre-line"
>
Description for autobone
</Typography>
</Localized>
</div>
</div>
<Button
variant="primary"
// Check if we are in dev mode and just let it be used
disabled={beneathFloor && import.meta.env.PROD}
to="/onboarding/body-proportions/auto"
className="self-start mt-auto"
state={{ alonePage: state.alonePage }}
@@ -186,16 +212,11 @@ export function ProportionsChoose() {
)
}
>
{l10n.getString('onboarding-choose_proportions-save')}
{l10n.getString('onboarding-choose_proportions-export')}
</Button>
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</>
);
}

View File

@@ -0,0 +1,64 @@
import { Localized, useLocalization } from '@fluent/react';
import ReactModal from 'react-modal';
import { BaseModal } from '../../../../commons/BaseModal';
import { WarningBox } from '../../../../commons/TipBox';
import { Button } from '../../../../commons/Button';
import { A } from '../../../../commons/A';
import { DOCS_SITE, SLIMEVR_DISCORD } from '../../../../../App';
export function AutoboneErrorModal({
isOpen = true,
onClose,
...props
}: {
/**
* Is the parent/sibling component opened?
*/
isOpen: boolean;
/**
* Function to trigger when closed or accepted
*/
onClose: () => void;
} & ReactModal.Props) {
const { l10n } = useLocalization();
return (
<BaseModal
isOpen={isOpen}
shouldCloseOnOverlayClick
shouldCloseOnEsc
onRequestClose={onClose}
className={props.className}
overlayClassName={props.overlayClassName}
>
<div className="flex w-full h-full flex-col ">
<div className="flex w-full flex-col flex-grow items-center gap-3">
<Localized
id="onboarding-automatic_proportions-error_modal"
elems={{
b: <b></b>,
docs: (
<A
href={`${DOCS_SITE}/server/body-config.html#common-issues--debugging`}
></A>
),
discord: <A href={SLIMEVR_DISCORD}></A>,
}}
>
<WarningBox>
<b>Warning:</b> An autobone error happened!
</WarningBox>
</Localized>
<div className="flex flex-row gap-3 pt-5 place-content-center">
<Button variant="primary" onClick={onClose}>
{l10n.getString(
'onboarding-automatic_proportions-error_modal-confirm'
)}
</Button>
</div>
</div>
</div>
</BaseModal>
);
}

View File

@@ -1,22 +1,49 @@
import { useEffect } from 'react';
import { useAutobone } from '../../../../../hooks/autobone';
import { ReactNode, useEffect, useState } from 'react';
import { ProcessStatus, useAutobone } from '../../../../../hooks/autobone';
import { ProgressBar } from '../../../../commons/ProgressBar';
import { TipBox } from '../../../../commons/TipBox';
import { Typography } from '../../../../commons/Typography';
import { useLocalization } from '@fluent/react';
import { P, match } from 'ts-pattern';
import { AutoboneErrorModal } from './AutoboneErrorModal';
export function Recording({ nextStep }: { nextStep: () => void }) {
export function Recording({
nextStep,
resetSteps,
}: {
nextStep: () => void;
resetSteps: () => void;
}) {
const { l10n } = useLocalization();
const { progress, hasCalibration, hasRecording } = useAutobone();
const { progress, hasCalibration, hasRecording, eta } = useAutobone();
const [modalOpen, setModalOpen] = useState(false);
useEffect(() => {
if (progress === 1 && hasCalibration) {
if (
hasRecording === ProcessStatus.REJECTED ||
hasCalibration === ProcessStatus.REJECTED
) {
setModalOpen(true);
}
if (progress !== 1) return;
if (
hasRecording === ProcessStatus.FULFILLED &&
hasCalibration === ProcessStatus.FULFILLED
) {
nextStep();
}
}, [progress, hasCalibration]);
}, [progress, hasCalibration, hasRecording]);
return (
<div className="flex flex-col items-center w-full justify-between">
<AutoboneErrorModal
isOpen={modalOpen}
onClose={() => {
setModalOpen(false);
resetSteps();
}}
></AutoboneErrorModal>
<div className="flex gap-1 flex-col justify-center items-center">
<div className="flex text-status-critical justify-center items-center gap-1">
<div className="w-2 h-2 rounded-lg bg-status-critical"></div>
@@ -51,19 +78,39 @@ export function Recording({ nextStep }: { nextStep: () => void }) {
<TipBox>{l10n.getString('tips-do_not_move_heels')}</TipBox>
</div>
<div className="flex flex-col gap-2 items-center w-full max-w-[150px]">
<ProgressBar progress={progress} height={2}></ProgressBar>
<ProgressBar
progress={progress}
height={2}
colorClass={match([hasCalibration, hasRecording])
.returnType<string | undefined>()
.with(
P.union(
[ProcessStatus.REJECTED, P._],
[P._, ProcessStatus.REJECTED]
),
() => 'bg-status-critical'
)
.with(
[ProcessStatus.FULFILLED, ProcessStatus.FULFILLED],
() => 'bg-status-success'
)
.otherwise(() => undefined)}
></ProgressBar>
<Typography color="secondary">
{!hasCalibration && hasRecording
? l10n.getString(
{match([hasCalibration, hasRecording])
.returnType<ReactNode>()
.with([ProcessStatus.PENDING, ProcessStatus.FULFILLED], () =>
l10n.getString(
'onboarding-automatic_proportions-recording-processing'
)
: l10n.getString(
)
.with([ProcessStatus.PENDING, ProcessStatus.PENDING], () =>
l10n.getString(
'onboarding-automatic_proportions-recording-timer',
{
// TODO: The progress should be communicated by the server in SolarXR
time: Math.round(20 * (1 - progress)),
}
)}
{ time: Math.round(eta) }
)
)
.otherwise(() => '')}
</Typography>
</div>
</div>

View File

@@ -1,5 +1,5 @@
import classNames from 'classnames';
import { useAutobone } from '../../../../../hooks/autobone';
import { ProcessStatus, useAutobone } from '../../../../../hooks/autobone';
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { useLocalization } from '@fluent/react';
@@ -69,13 +69,14 @@ export function VerifyResultsStep({
<Typography bold>{(value * 100).toFixed(2)} CM</Typography>
</div>
))}
{!hasCalibration && hasRecording && (
<Typography>
{l10n.getString(
'onboarding-automatic-proportions-verify-results-processing'
)}
</Typography>
)}
{hasCalibration === ProcessStatus.PENDING &&
hasRecording === ProcessStatus.FULFILLED && (
<Typography>
{l10n.getString(
'onboarding-automatic-proportions-verify-results-processing'
)}
</Typography>
)}
</div>
</div>
</div>

View File

@@ -0,0 +1,176 @@
import {
AutoBoneSettingsT,
ChangeSettingsRequestT,
HeightRequestT,
HeightResponseT,
RpcMessage,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../../../hooks/websocket-api';
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { Localized, useLocalization } from '@fluent/react';
import { useForm } from 'react-hook-form';
import { useMemo, useState } from 'react';
import { NumberSelector } from '../../../../commons/NumberSelector';
import { DEFAULT_HEIGHT, MIN_HEIGHT } from '../ProportionsChoose';
import { useLocaleConfig } from '../../../../../i18n/config';
import { useCountdown } from '../../../../../hooks/countdown';
interface HeightForm {
height: number;
hmdHeight: number;
}
export function CheckHeight({
nextStep,
prevStep,
variant,
}: {
nextStep: () => void;
prevStep: () => void;
variant: 'onboarding' | 'alone';
}) {
const { l10n } = useLocalization();
const { control, handleSubmit, setValue } = useForm<HeightForm>();
const [fetchedHeight, setFetchedHeight] = useState(false);
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
const { timer, isCounting, startCountdown } = useCountdown({
duration: 3,
onCountdownEnd: () => {
setFetchedHeight(true);
sendRPCPacket(RpcMessage.HeightRequest, new HeightRequestT());
},
});
const { currentLocales } = useLocaleConfig();
const mFormat = useMemo(
() =>
new Intl.NumberFormat(currentLocales, {
style: 'unit',
unit: 'meter',
maximumFractionDigits: 2,
}),
[currentLocales]
);
const sFormat = useMemo(
() => new Intl.RelativeTimeFormat(currentLocales, { style: 'short' }),
[currentLocales]
);
useRPCPacket(
RpcMessage.HeightResponse,
({ hmdHeight, estimatedFullHeight }: HeightResponseT) => {
setValue('height', estimatedFullHeight || DEFAULT_HEIGHT);
setValue('hmdHeight', hmdHeight);
}
);
const onSubmit = (values: HeightForm) => {
const changeSettings = new ChangeSettingsRequestT();
const autobone = new AutoBoneSettingsT();
autobone.targetFullHeight = values.height;
autobone.targetHmdHeight = values.hmdHeight;
changeSettings.autoBoneSettings = autobone;
sendRPCPacket(RpcMessage.ChangeSettingsRequest, changeSettings);
nextStep();
};
return (
<>
<div className="flex flex-col flex-grow">
<div className="flex flex-grow flex-col gap-4">
<Typography variant="main-title" bold>
{l10n.getString(
'onboarding-automatic_proportions-check_height-title'
)}
</Typography>
<div>
<Typography color="secondary">
{l10n.getString(
'onboarding-automatic_proportions-check_height-description'
)}
</Typography>
<Localized
id="onboarding-automatic_proportions-check_height-calculation_warning"
elems={{ u: <span className="underline"></span> }}
>
<Typography color="secondary" bold>
Press the button to get your height!
</Typography>
</Localized>
<Button
variant="primary"
className="mt-2"
onClick={startCountdown}
disabled={isCounting}
>
{isCounting
? sFormat.format(timer, 'second')
: l10n.getString(
'onboarding-automatic_proportions-check_height-fetch_height'
)}
</Button>
</div>
<form className="flex flex-col self-center items-center justify-center">
<NumberSelector
control={control}
name="height"
label={l10n.getString(
'onboarding-automatic_proportions-check_height-height'
)}
valueLabelFormat={(value) =>
isNaN(value)
? l10n.getString(
'onboarding-automatic_proportions-check_height-unknown'
)
: mFormat.format(value)
}
min={MIN_HEIGHT}
max={4}
step={0.01}
/>
<NumberSelector
control={control}
name="hmdHeight"
label={l10n.getString(
'onboarding-automatic_proportions-check_height-hmd_height'
)}
valueLabelFormat={(value) =>
isNaN(value)
? l10n.getString(
'onboarding-automatic_proportions-check_height-unknown'
)
: mFormat.format(value)
}
min={MIN_HEIGHT}
max={4}
step={0.01}
disabled={true}
/>
</form>
</div>
<div className="flex gap-3 mobile:justify-between">
<Button
variant={variant === 'onboarding' ? 'secondary' : 'tertiary'}
onClick={prevStep}
>
{l10n.getString('onboarding-automatic_proportions-prev_step')}
</Button>
<Button
variant="primary"
onClick={handleSubmit(onSubmit)}
disabled={!fetchedHeight}
>
{l10n.getString(
'onboarding-automatic_proportions-check_height-next_step'
)}
</Button>
</div>
</div>
</>
);
}

View File

@@ -6,9 +6,6 @@ import { MountingResetStep } from './mounting-steps/MountingReset';
import { PreparationStep } from './mounting-steps/Preparation';
import { PutTrackersOnStep } from './mounting-steps/PutTrackersOn';
import { useLocalization } from '@fluent/react';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { useState } from 'react';
import { SkipSetupButton } from '../../SkipSetupButton';
const steps: Step[] = [
{ type: 'numbered', component: PutTrackersOnStep },
@@ -18,19 +15,13 @@ const steps: Step[] = [
];
export function AutomaticMountingPage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { applyProgress, state } = useOnboarding();
applyProgress(0.7);
return (
<>
<div className="flex flex-col gap-2 h-full items-center w-full xs:justify-center relative overflow-y-auto overflow-x-hidden px-4 pb-4">
<SkipSetupButton
visible={!state.alonePage}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex flex-col w-full h-full xs:justify-center xs:max-w-3xl gap-5">
<div className="flex flex-col xs:max-w-lg gap-3">
<Typography variant="main-title">
@@ -48,11 +39,6 @@ export function AutomaticMountingPage() {
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</>
);
}

View File

@@ -11,16 +11,14 @@ import { Typography } from '../../../commons/Typography';
import { BodyAssignment } from '../../BodyAssignment';
import { MountingSelectionMenu } from './MountingSelectionMenu';
import { useLocalization } from '@fluent/react';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupButton } from '../../SkipSetupButton';
import { useBreakpoint } from '../../../../hooks/breakpoint';
import { Quaternion } from 'three';
export function ManualMountingPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const { applyProgress, state } = useOnboarding();
const { sendRPCPacket } = useWebsocketAPI();
const [skipWarning, setSkipWarning] = useState(false);
const [selectedRole, setSelectRole] = useState<BodyPart>(BodyPart.NONE);
@@ -44,7 +42,7 @@ export function ManualMountingPage() {
[assignedTrackers]
);
const onDirectionSelected = (mountingOrientationDegrees: number) => {
const onDirectionSelected = (mountingOrientationDegrees: Quaternion) => {
(trackerPartGrouped[selectedRole] || []).forEach((td) => {
const assignreq = new AssignTrackerRequestT();
@@ -55,6 +53,7 @@ export function ManualMountingPage() {
assignreq.trackerId = td.tracker.trackerId;
assignreq.allowDriftCompensation =
td.tracker.info?.allowDriftCompensation ?? true;
assignreq.accessoryId = td.tracker.info?.accessoryId || 0;
sendRPCPacket(RpcMessage.AssignTrackerRequest, assignreq);
});
@@ -65,16 +64,12 @@ export function ManualMountingPage() {
return (
<>
<MountingSelectionMenu
bodyPart={selectedRole}
isOpen={selectedRole !== BodyPart.NONE}
onClose={() => setSelectRole(BodyPart.NONE)}
onDirectionSelected={onDirectionSelected}
></MountingSelectionMenu>
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center relative overflow-y-auto">
<SkipSetupButton
visible={!state.alonePage}
modalVisible={skipWarning}
onClick={() => setSkipWarning(true)}
></SkipSetupButton>
<div className="flex xs:flex-row mobile:flex-col h-full px-8 xs:w-full xs:justify-center mobile:px-4 items-center">
<div className="flex flex-col w-full xs:max-w-sm gap-3">
<Typography variant="main-title">
@@ -109,11 +104,6 @@ export function ManualMountingPage() {
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</>
);
}

Some files were not shown because too many files have changed in this diff Show More