Compare commits

...

65 Commits

Author SHA1 Message Date
Erimel
a0e4096701 Merge pull request #738 from SlimeVR/pontoon
New Pontoon translations
2023-06-20 18:53:18 -04:00
Uriel
5c7c7423cc Pontoon: Update Latinamerican Spanish (es-419) localization of GUI
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-06-20 22:47:14 +00:00
namakeingo
a715818421 Pontoon: Update Italian (it) localization of GUI
Co-authored-by: namakeingo <namakeingo@gmail.com>
2023-06-20 22:47:09 +00:00
Erimel
1f947965dc Pontoon: Update French (fr) localization of GUI
Co-authored-by: Erimel <loukalemire@gmail.com>
2023-06-20 22:47:05 +00:00
Uriel
366a255887 Finally fix small window (#731) 2023-06-20 14:14:33 +03:00
Uriel
d6862f13aa Fix trackerError status returning empty object on null device (#735) 2023-06-20 14:11:15 +03:00
Lena
dcfa5ede78 Updates the recommended mounting method to manual (#734) 2023-06-20 14:10:08 +03:00
Butterscotch!
652b44d50b PoseFrame fix & AutoBone change (#736) 2023-06-19 17:32:13 +03:00
Lena
3e2d7bb1f2 Rename save proportions to export proportion (#732) 2023-06-16 16:06:17 +03:00
Uriel
ce3731f381 fix trackerName logic for error status (#715) 2023-06-16 00:27:47 +03:00
Uriel
28b37b73e7 Fix reset status on yaw reset (#730) 2023-06-16 00:20:12 +03:00
Butterscotch!
f7b4a60448 Tracking pause fixes (#721) 2023-06-16 00:16:50 +03:00
Erimel
66214bae76 Fix allowDriftCompensation setting to false on mounting or assign (#717) 2023-06-15 22:17:34 +03:00
Collin Kees
25cb8cc9c6 Potential floorclip fixes (#728)
* maybe fix floor clip randomly breaking

* spotless
2023-06-15 15:10:30 -04:00
SlimeVR-bot
379084493b New Pontoon translations (#703)
* Pontoon: Update German (de) localization of GUI

Co-authored-by: unlogisch <unlogisch@gmx.ch>
Co-authored-by: TheDevMinerTV <devminer@devminer.xyz>

* Pontoon: Update French (fr) localization of GUI

Co-authored-by: Toonmomo <anthony.maurice.pro@gmail.com>
Co-authored-by: Erimel <loukalemire@gmail.com>
Co-authored-by: jojos38000 <jojos38000@hotmail.com>

* Pontoon: Update Engwish (en-x-owo) localization of GUI

Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>

* Pontoon: Update Latinamerican Spanish (es-419) localization of GUI

Co-authored-by: Arc#8355 <tikkodesign@hotmail.com>
Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Pontoon: Update Polish (pl) localization of GUI

Co-authored-by: ReDoX <redox01@o2.pl>

* Pontoon: Update Simplified Chinese (zh-Hans) localization of GUI

Co-authored-by: Disappear9 <disappear9@outlook.com>

* Pontoon: Update Traditional Chinese (zh-Hant) localization of GUI

Co-authored-by: Meow Wei <medicalwei@gmail.com>

* Pontoon: Update Japanese (ja) localization of GUI

Co-authored-by: beq <beqbdean@gmail.com>

* Pontoon: Update Arabic (ar) localization of GUI

Co-authored-by: Uriel <urielfontan2002@gmail.com>

---------

Co-authored-by: unlogisch <unlogisch@gmx.ch>
Co-authored-by: TheDevMinerTV <devminer@devminer.xyz>
Co-authored-by: Erimel <loukalemire@gmail.com>
Co-authored-by: Toonmomo <anthony.maurice.pro@gmail.com>
Co-authored-by: jojos38000 <jojos38000@hotmail.com>
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: Arc#8355 <tikkodesign@hotmail.com>
Co-authored-by: ReDoX <redox01@o2.pl>
Co-authored-by: Disappear9 <disappear9@outlook.com>
Co-authored-by: Meow Wei <medicalwei@gmail.com>
Co-authored-by: beq <beqbdean@gmail.com>
2023-06-15 09:01:16 -04:00
NWB
5fe2480662 Do Not Send Erroneous Battery Readings to SteamVR (#712)
* Potential SteamVR Low Battery Fix

May fix low battery icon issue with DIY trackers that use internal battery sensing.

* Small change & Comments

More comments on expected battery range and adjustments on what battery voltages to use.

* minor changes

changed battery battery voltages

* changed voltages again

* High battery reading rejection

Don't send very high battery readings

* Updated comments

updated comments a bit
2023-06-14 09:49:26 -04:00
Butterscotch!
fc13a8385c [AutoBone] Fix player trackers not being found or assigned in HumanSkeleton (#722) 2023-06-13 22:54:45 -04:00
lucas lelievre
5d9d545346 Fix width of Tracker assign in desktop + Fix min height of the window (#720) 2023-06-13 18:18:00 -04:00
lucas lelievre
91c0ea85a6 Mobile gui basics (#713)
* Mobile implementation without settings and widgets

* Working Settings and widgets + Few tweaks for responsive

* Make linter happy

* Update gui/src/components/Navbar.tsx

Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Update gui/src/components/onboarding/pages/CalibrationTutorial.tsx

Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Update gui/src/components/onboarding/pages/CalibrationTutorial.tsx

Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Update gui/src/components/onboarding/pages/CalibrationTutorial.tsx

Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Update gui/src/components/onboarding/pages/CalibrationTutorial.tsx

Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Update gui/src/components/settings/pages/Serial.tsx

Co-authored-by: Uriel <urielfontan2002@gmail.com>

* Apply review changes

* Revert removing full height in body

* Fix onboarding manual body proportions on mobile

* make connect trackers page work on mobile

* Apply suggestions from code review

Co-authored-by: DevMiner <devminer@devminer.xyz>

* Applie required changes

* rollback server ip

* Remove placeholder string

* Remove unused isMobile

* Remove unused isMobile

* error on unused vars

* make it warn but make the lint script error on warnings

---------

Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: DevMiner <devminer@devminer.xyz>
2023-06-11 18:50:54 -04:00
Uriel
841ea8ee94 add lots of stuff (#704) 2023-06-12 00:07:35 +03:00
Uriel
788414f8f6 fix nix errors (#714) 2023-06-11 17:36:11 +03:00
Uriel
f944a07377 Fix bundling for mac (#711) 2023-06-09 17:47:32 +03:00
Erimel
8d328e1a27 Add niche option to always use floorclip (#710) 2023-06-07 14:54:20 +03:00
Uriel
4ba2bb0dca Fix GUI bugs (#707) 2023-06-07 14:53:32 +03:00
Eiren Rain
011f31a64d Update README about translation 2023-06-04 19:52:42 +02:00
Uriel
c0e42c2d45 Add more tutorials on setup (#696)
Co-authored-by: Erimel <marioluigivideo@gmail.com>
2023-06-01 21:42:02 +03:00
NWB
6a9b5cda1d Send Tracker Battery Info to SteamVR (#668)
* implement battery support

Co-authored-by: NWB <n3rt46@gmail.com>

* undo solarxr

* spotless

* Improved battery level aggregation

When chest and knee trackers are disabled in SteamVR, they should now aggregate their battery level with waist and foot trackers respectively.

Moved SteamVR-specific writeBatteryUpdate() and batteryReceived() to SteamVRBridge. Some battery stuff is still left in ProtobufBridge, but only what's necessary.

* Aggregate Waist and Hip with Chest

When waist is disabled, and chest is enabled, waist and hip battery levels will aggregate with the chest tracker.

* Comments & Minor Fixes

Added descriptive comments, and fixed lowestLevel not checking for >= 200. Also fixed right knee aggregating with right ankle/foot.

* Spotless

Applied spotless.

* Spotless

Applied spotless >_>

---------

Co-authored-by: ImUrX <urielfontan2002@gmail.com>
Co-authored-by: Erimel <marioluigivideo@gmail.com>
2023-05-31 20:37:46 -04:00
Butterscotch!
760f775d60 Fix height calculation and targetHeight order (#705) 2023-05-31 19:34:45 -04:00
Uriel
309e78e47c Some more random improvements (#695) 2023-05-29 20:29:01 +03:00
Uriel
1f2fbfc101 Status system (#689)
Co-authored-by: Louka <marioluigivideo@gmail.com>
2023-05-29 20:10:27 +03:00
Butterscotch!
88dbb15ae2 Add tracking pausing (#697) 2023-05-29 19:21:54 +03:00
Collin Kees
eb91878257 Better foot plant (#691)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-05-29 19:19:43 +03:00
Uriel
d1cd7776f3 Require the use of run command for running server (#701)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-05-29 19:06:09 +03:00
Uriel
797fcab208 Add minimization (#700) 2023-05-29 19:05:12 +03:00
Butterscotch!
1fc3c95711 Fix BVH translation comment (#698) 2023-05-29 00:20:20 -04:00
Erimel
8ac0de0601 Fix legtweaks knees condition (#702) 2023-05-28 02:33:21 +03:00
Erimel
c3e2396ed6 Merge pull request #659 from SlimeVR/pontoon
New Pontoon translations
2023-05-26 18:54:19 -04:00
TheDevMinerTV
40ea2656c2 Pontoon: Update German (de) localization of GUI
Co-authored-by: rex <rexvizsla@gmail.com>
Co-authored-by: TheDevMinerTV <devminer@devminer.xyz>
Co-authored-by: Piranja <info@hollihn.ch>
2023-05-26 12:45:25 -03:00
ImUrX
c5bc2ef55b Add Danish language option 2023-05-26 12:45:24 -03:00
viwas45hu978ot
c54e1ac79b Pontoon: Update Danish (da) localization of GUI
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: viwas45hu978ot <viwashuot@gmail.com>
Co-authored-by: Sacchi <therollocat@gmail.com>
2023-05-26 12:45:23 -03:00
patsakorn9090
7832ff7488 Pontoon: Update Thai (th) localization of GUI
Co-authored-by: patsakorn9090 <patsakorn9090@gmail.com>
2023-05-26 12:45:22 -03:00
Vyolex
6ab54098d9 Pontoon: Update Dutch (nl) localization of GUI
Co-authored-by: Vyolex <25586367+Vyolex@users.noreply.github.com>
2023-05-26 12:45:15 -03:00
Siofra
48e3dd363e Pontoon: Update Finnish (fi) localization of GUI
Co-authored-by: Siofra <maradaichides@gmail.com>
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-05-26 12:45:12 -03:00
Kamilake
2b26983d0b Pontoon: Update Korean (ko) localization of GUI
Co-authored-by: Kamilake <exjang0@gmail.com>
2023-05-26 12:45:11 -03:00
Uriel
b4cbe18e28 Pontoon: Update Russian (ru) localization of GUI
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: Hornil <vixlyaev@gmail.com>
2023-05-26 12:45:10 -03:00
Erimel
cc75128acf Pontoon: Update French (fr) localization of GUI
Co-authored-by: the1pigeon <the1pigeon@gmail.com>
Co-authored-by: Erimel <loukalemire@gmail.com>
2023-05-26 12:45:09 -03:00
Meow Wei
920670ac1b Pontoon: Update Traditional Chinese (zh-Hant) localization of GUI
Co-authored-by: Meow Wei <medicalwei@gmail.com>
Co-authored-by: 白貓 <yen.max@gmail.com>
2023-05-26 12:45:03 -03:00
Disappear9
2689b06523 Pontoon: Update Simplified Chinese (zh-Hans) localization of GUI
Co-authored-by: Disappear9 <disappear9@outlook.com>
Co-authored-by: Meow Wei <medicalwei@gmail.com>
Co-authored-by: Antenna <vv03A24@foxmail.com>
2023-05-26 12:44:55 -03:00
ReDoX
cbcd2dc8ce Pontoon: Update Polish (pl) localization of GUI
Co-authored-by: ReDoX <redox01@o2.pl>
2023-05-26 12:44:44 -03:00
FennT
eb266ac2a4 Pontoon: Update Arabic (ar) localization of GUI
Co-authored-by: FennT <0094falcon@gmail.com>
2023-05-21 23:36:38 -03:00
Butterscotch!
8f1aa5c016 Pontoon: Update Engwish (en-x-owo) localization of GUI
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-05-21 23:36:21 -03:00
namakeingo
c24cf1ed81 Pontoon: Update Italian (it) localization of GUI
Co-authored-by: namakeingo <namakeingo@gmail.com>
Co-authored-by: Etch9 <mario.mazzara30@gmail.com>
2023-05-21 23:35:59 -03:00
Erimel
a1b91ee111 Log yaw drift and reset all trackers (#682)
Cauthored-by: Butterscotch! <bscotchvanilla@gmail.com>
Co-authored-by: ImUrX <urielfontan2002@gmail.com>
2023-05-21 17:42:01 +03:00
NWB
9af7fecd88 Additional Theme Options (#671) 2023-05-19 20:23:09 +03:00
Erimel
64b0dceb50 Basic version update checking (#690)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-05-19 20:21:30 +03:00
Uriel
d652c3eb9b Calibration tutorial (#687) 2023-05-19 20:19:09 +03:00
Uriel
8bc8be9b90 Fix the reason of my suffering (#693) 2023-05-17 15:50:17 +03:00
Uriel
2b4676676d Tap setup (#667)
Co-authored-by: Stermere <collin@kees.net>
2023-05-17 15:36:55 +03:00
Uriel
2c62e0bd72 Convert UDP Server stuff to Kotlin (#683)
Co-authored-by: Louka <marioluigivideo@gmail.com>
2023-05-17 15:18:29 +03:00
Erimel
d4068e7ccb Trackers rewrite & Switch to new math lib (#647)
Co-authored-by: ImUrX <urielfontan2002@gmail.com>
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-05-17 01:55:52 +03:00
Erimel
e570943ec5 Update contributing information (#673)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-05-10 20:57:23 +03:00
Uriel
2486121ede More GUI fixes (#678)
Co-authored-by: ButterscotchV <bscotchvanilla@gmail.com>
2023-05-02 19:33:57 +03:00
Ryan Butler
1c9fe71829 Update VRServer.java with important change (#685)
furries run SlimeVR
2023-04-25 00:42:11 +03:00
Erimel
09fc604a53 Improve vrchat osctrackers text (#675)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
2023-04-25 00:31:46 +03:00
Erimel
a20abb9abe fix left foot icon being reversed (#672) 2023-04-15 15:44:02 +03:00
309 changed files with 24375 additions and 27848 deletions

View File

@@ -197,7 +197,7 @@ jobs:
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 \
--volicon ../macos/slimevr.app/Contents/Resources/slimevr.icns --skip-jenkins \
--volicon ../macos/slimevr.app/Contents/Resources/icon.icns --skip-jenkins \
--eula ../../../../LICENSE-MIT slimevr.dmg ../macos/slimevr.app
- uses: actions/upload-artifact@v3.1.0

View File

@@ -27,6 +27,7 @@ jobs:
git config --local user.email pantoon@slimevr.dev
git fetch origin main
git rebase origin/main
git submodule update
- name: Push rebase
uses: github-actions-x/commit@v2.9
with:

View File

@@ -1,50 +1,66 @@
# Contributing to SlimeVR
This document describes essential knowledge for contributors to SlimeVR.
This document describes essential knowledge required to contribute to the SlimeVR Server.
## How to get started
### Prerequisites
### Getting the code
First, clone the codebase using `git`. If you don't have `git` installed, go install it.
- [Git](https://git-scm.com/downloads)
- [Java v17+](https://adoptium.net/temurin/releases/)
- [Node.js v16+](https://nodejs.org) (We recommend the use of `nvm` instead of installing Node.js directly)
- [Microsoft Edge WebView2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section) or `webkit2gtk` for Linux
- [Rust](https://rustup.rs)
## Cloning the code
First, clone the codebase using git in a terminal in the folder you want.
```bash
# Clone repositories
git clone --recursive https://github.com/SlimeVR/SlimeVR-Server.git
# Enter the directory of the codebase
cd SlimeVR-Server
```
Now you can open the codebase in your favorite IDE or text editor.
### Installing Java
The codebase is required to build with Java version 17 or higher.
```bash
# Check java version
java --version
```
Now you can open the codebase in [IDEA](https://www.jetbrains.com/idea/download/) (Recommended; VSCode and Eclipse also work but have limited Kotlin support).
### Building the code
The code is built with `gradle`, a cli tool that manages java projects and their
dependencies. You can build the code with `./gradlew build` and run it with
`./gradlew run`.
## Building the code
### Java (server)
## Code Style
Code is autoformatted with [spotless](https://github.com/diffplug/spotless/tree/main/plugin-gradle).
The Java code is built with `gradle`, a CLI tool that manages java projects and their
dependencies.
- You can run the server by running `./gradlew run` in your IDE's terminal.
- To compile the code, run `./gradlew shadowJar`. The result will
be at `server/build/libs/slimevr.jar` (you can ignore `server.jar`).
(Note: Your IDE may be able to do all of the above for you.)
### Tauri (gui)
- Run `npm install` in your IDE's terminal to download and install dependencies.
- To launch the GUI in dev mode, run `npm run gui`.
- Finally, to compile for production, run `npm run tauri build`. The result
will be at `target/release/slimevr.exe`.
## Code style
### Java (server)
The Java code is auto-formatted with [spotless](https://github.com/diffplug/spotless/tree/main/plugin-gradle).
Code is checked for autoformatting whenever you build, but you can also run
`./gradlew spotlessCheck` if you prefer.
To autoformat your code from the command line, you can run `./gradlew spotlessApply`.
We recommend installing support for spotless in your IDE of choice, and formatting
whenever you save a file, to make things easy.
To auto-format your Java and Kotlin code from the command line, you can run `./gradlew spotlessApply`.
We recommend installing support for spotless in your IDE, and formatting
whenever you save a file to make things easy.
If you need to prevent autoformatting for a particular region of code, use
If you need to prevent autoformatting for a select region of code, use
`// @formatter:off` and `// @formatter:on`
### Setting up spotless in VSCode
#### Setting up spotless for IntelliJ IDEA
* Install https://plugins.jetbrains.com/plugin/18321-spotless-gradle
* Add a keyboard shortcut for `Code` > `Reformat Code with Spotless`
* They are working on support to do this on save without a keybind
[here](https://github.com/ragurney/spotless-intellij-gradle/issues/8)
#### Setting up spotless for VSCode
* Install the `richardwillis.vscode-spotless-gradle` extension
* Add the following to your workspace settings, at `.vscode/settings.json`:
```json
@@ -55,13 +71,7 @@ If you need to prevent autoformatting for a particular region of code, use
}
```
### Setting up spotless for IntelliJ
* Install https://plugins.jetbrains.com/plugin/18321-spotless-gradle.
* Add a keyboard shortcut for `Code` > `Reformat Code with Spotless`
* They are working on support to do this on save without a keybind
[here](https://github.com/ragurney/spotless-intellij-gradle/issues/8)
### Setting up Eclipse autoformatting
#### Setting up Eclipse autoformatting
Import the formatting settings defined in `spotless.xml`, like this:
* Go to `File > Properties`, then `Java Code Style > Formatter`
* Check `Enable project specific settings`
@@ -73,19 +83,31 @@ Import the formatting settings defined in `spotless.xml`, like this:
Eclipse will only do a subset of the checks in `spotless`, so you may still want to do
`./gradlew spotlessApply` if you ever see an error from spotless.
### Version bumping
* Add new release inside ``<releases>`` in the ``dev.slimevr.SlimeVR.metainfo.xml`` file. (Example: ``<release version="a.b.c" date="YYYY-MM-DD"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/va.b.c</url></release>``)
* Create the git tag instead of making it from releases, you can do it by just ``git tag VERSION``,
example ``git tag v0.5.0``
* You need to push this change with ``git push origin VERSION`` or ``git push origin --tags``
(will push all tags you made).
### Tauri (gui)
We recommend committing first and then making the tag, that tag will point to the commit you are currently
on.
We use ESLint and Prettier to format GUI code.
- First, go into the GUI's directory with your terminal by running `cd gui`.
- To check code formatting, run `npm run lint`.
- To fix code formatting, run `npm run lint:fix` and `npm run format`
Don't forget to run `cd ..` to return to the root directory.
## SolarXR Protocol
SolarXR is used to communicate between the server (backend) and GUI (frontend).
It can also be used to communicate to third party applications.
When touching SolarXR:
- You will need `flatc`. To know which version to get, refer to
[SolarXR's README](https://github.com/SlimeVR/SolarXR-Protocol/blob/main/README.md#flatc)
- The only files you should edit are in the `schema` directory.
- After editing files, you should run `cd solarxr-protocol`, then either run
`./generate-flatbuffer.ps1` (Windows) or `./generate-flatbuffer.sh` (Linux/OSX)
- Make sure to commit your changes inside the submodule.
## Code Licensing
SlimeVR uses dual MIT and Apache-2.0 license. Be sure that any code that you reference,
or dependencies you add, are compatible with these licenses. `GPL-v3` for example is
or dependencies you add, are compatible with these licenses. For example, `GPL-v3` is
not compatible because it requires any and all code that depends on it to *also* be
licensed under `GPL-v3`.

1494
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,20 +9,28 @@ Sensors implementations:
* [SlimeVR Wrangler](https://github.com/carl-anders/slimevr-wrangler) - use Nintendo Switch Joycon controllers as trackers
Integrations:
* Use [SlimeVR OpenVR Driver](https://github.com/SlimeVR/SlimeVR-OpenVR-Driver) as a driver for SteamVR
* Use built-in OSC support for integration with other apps, such as VRChat, using OSC
* Integrations with other systems will be added later
* Use [SlimeVR OpenVR Driver](https://github.com/SlimeVR/SlimeVR-OpenVR-Driver) as a driver for SteamVR.
* Use built-in OSC Trackers support for FBT integration with VRChat, PCVR or Standalone.
* Use built-in VMC support for sending and receiving tracking data to and from other apps such as VSeeFace.
* Export recordings as .BVH files to integrate motion capture data into 3d applications such as Blender.
## How to use
## Installing
It's highly recommended to install using the installer downloadable here: https://github.com/SlimeVR/SlimeVR-Installer/releases/latest/download/slimevr_web_installer.exe
Latest setup instructions are [on our site](https://docs.slimevr.dev/server/index.html).
Latest setup instructions are [in our docs](https://docs.slimevr.dev/server/index.html).
## Building & Contributing
For information on building and contributing to the codebase, see [CONTRIBUTING.md](CONTRIBUTING.md).
## Translating
Translation is done via Pontoon at [i18n.slimevr.dev](https://i18n.slimevr.dev/). Please join our [Discord translation forum](https://discord.com/channels/817184208525983775/1050413434249949235) to coordinate.
## License clarification
**SlimeVR software** (including server, firmware, drivers, installer, documents, and others - see
licence for each case specifically) **is distributed under a dual MIT/Apache 2.0 License
([LICENSE-MIT] and [LICENSE-APACHE]). The software is the copyright of the SlimeVR
contributors.**
contributors.**
**However, these licenses have some limits, and if you wish to distribute software based
on SlimeVR, you need to be aware of them:**
@@ -54,7 +62,5 @@ You also certify that the code you have used is compatible with those licenses o
authored by you. If you're doing so on your work time, you certify that your employer is
okay with this and that you are authorized to provide the above licenses.
For a how-to on contributing, see [CONTRIBUTING.md](CONTRIBUTING.md).
[LICENSE-MIT]: LICENSE-MIT
[LICENSE-APACHE]: LICENSE-APACHE

26
build.gradle.kts Normal file
View File

@@ -0,0 +1,26 @@
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)
}

66
flake.lock generated
View File

@@ -1,12 +1,15 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
@@ -16,12 +19,15 @@
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
@@ -32,11 +38,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1677407201,
"narHash": "sha256-3blwdI9o1BAprkvlByHvtEm5HAIRn/XPjtcfiunpY7s=",
"lastModified": 1686412476,
"narHash": "sha256-inl9SVk6o5h75XKC79qrDCAobTD1Jxh6kVYTZKHzewA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7f5639fa3b68054ca0b062866dc62b22c3f11505",
"rev": "21951114383770f96ae528d0ae68824557768e81",
"type": "github"
},
"original": {
@@ -47,11 +53,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1665296151,
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
"lastModified": 1681358109,
"narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
"rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9",
"type": "github"
},
"original": {
@@ -74,11 +80,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1675391458,
"narHash": "sha256-ukDKZw922BnK5ohL9LhwtaDAdCsJL7L6ScNEyF1lO9w=",
"lastModified": 1686364106,
"narHash": "sha256-h4gCQg+jizmAbdg6UPlhxQVk4A7Ar/zoLa0wx3wBya0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "383a4acfd11d778d5c2efcf28376cbd845eeaedf",
"rev": "ba011dd1c5028dbb880bc3b0f427e0ff689e6203",
"type": "github"
},
"original": {
@@ -86,6 +92,36 @@
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

View File

@@ -52,6 +52,10 @@
treefmt
webkitgtk
zlib
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
# Some nice things to have
exa

View File

@@ -6,3 +6,5 @@ org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAME
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
kotlin.code.style=official
# https://github.com/Kotlin/kotlinx-atomicfu#atomicfu-compiler-plugin
kotlinx.atomicfu.enableJvmIrTransformation=true

Binary file not shown.

View File

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

25
gradlew vendored
View File

@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# 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"'
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -143,12 +140,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -193,6 +194,10 @@ 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
@@ -205,6 +210,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

15
gradlew.bat vendored
View File

@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View File

@@ -1,6 +0,0 @@
This directory and all subdirectories are dual-licensed under either
* MIT License ([/LICENSE-MIT](/LICENSE-MIT))
* Apache License, Version 2.0 ([/LICENSE-APACHE](/LICENSE-APACHE))
at your option.

View File

@@ -1,30 +0,0 @@
# SlimeVR UI
This is the GUI of SlimeVR, it uses the SolarXR protocol to communicate with the server and is completely isolated from the server logic.
This project is written in Typescript + React for the frontend and uses Tauri + Rust as a small backend. This makes the application more lightweight than electron.
## Compiling
### Prerequisites
- [Node.js](https://nodejs.org) 16 (We recommend the use of `nvm` instead of installing Node.js directly)
- Windows Webview
- SlimeVR server installed
- [Rust](https://rustup.rs)
```
npm install
```
Build for production
```
npm run tauri build
```
Launch in dev mode
```
npm run tauri dev
```

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0" />
<meta name="theme-color" content="#000000" />
<link rel="apple-touch-icon" href="/logo192.png" />

View File

@@ -8,11 +8,12 @@
"@fontsource/poppins": "^4.5.8",
"@formatjs/intl-localematcher": "^0.2.32",
"@react-three/fiber": "^8.10.0",
"@tauri-apps/api": "^1.2.0",
"@tauri-apps/api": "^1.4.0",
"@vitejs/plugin-react": "^3.0.0",
"browserslist": "^4.18.1",
"classnames": "^2.3.1",
"eslint-config-react-app": "^7.0.0",
"file-saver": "^2.0.5",
"flatbuffers": "^22.10.26",
"identity-obj-proxy": "^3.0.0",
"intl-pluralrules": "^1.3.1",
@@ -26,7 +27,9 @@
"react-dom": "^18.0.0",
"react-hook-form": "^7.29.0",
"react-modal": "3.15.1",
"react-responsive": "^9.0.2",
"react-router-dom": "^6.2.2",
"semver": "^7.5.0",
"solarxr-protocol": "file:../solarxr-protocol",
"three": "^0.148.0",
"typescript": "^4.6.3"
@@ -37,7 +40,7 @@
"dev": "tauri dev",
"skipbundler": "tauri build -b none",
"tauri": "tauri",
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx,json}\" && prettier --check \"src/**/*.{js,jsx,ts,tsx,css,md,json}\"",
"lint": "eslint --max-warnings=0 \"src/**/*.{js,jsx,ts,tsx,json}\" && prettier --check \"src/**/*.{js,jsx,ts,tsx,css,md,json}\"",
"lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx,json}\"",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md,json}\"",
"preview-vite": "vite preview",
@@ -62,13 +65,14 @@
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.0",
"@tauri-apps/cli": "^1.2.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.43.0",
"@typescript-eslint/parser": "^5.43.0",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.0",
"autoprefixer": "^10.4.4",
"cross-env": "^7.0.3",
"eslint": "^8.18.0",

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 = لست متأكد من أجهزة التعقب؟ قم بتحريك الجهاز لتحديد العنصر المناسب.
@@ -95,11 +95,14 @@ navbar-mounting = معايرة التركيب
navbar-onboarding = معالج الإعداد
navbar-settings = الإعدادات
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = سجل بي في ايتش
bvh-recording = تسجيل...
## Tracking pause
## Widget: Overlay settings
widget-overlay = التراكب
@@ -126,6 +129,7 @@ widget-developer_mode-more_info = المزيد
widget-imu_visualizer = دوران
widget-imu_visualizer-rotation_raw = صافي
widget-imu_visualizer-rotation_preview = عرض مسبق
widget-imu_visualizer-rotation_hide = إخفاء
## Tracker status
@@ -252,6 +256,7 @@ settings-sidebar-fk_settings = إعدادات التعقب
settings-sidebar-gesture_control = التحكم بالإيماءات
settings-sidebar-interface = واجهة المستخدم
settings-sidebar-osc_router = راوتر أوه أس سي
settings-sidebar-osc_trackers = أجهزة تعقب في ار تشات أوه أس سي
settings-sidebar-utils = الأدوات المساعدة
settings-sidebar-serial = وحدة التحكم التسلسلية
@@ -369,6 +374,7 @@ 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 = اختر اللغة التي تريد استخدامها
@@ -443,7 +449,7 @@ settings-osc-vrchat-network-address-placeholder = عنوان آي بي الخا
settings-osc-vrchat-network-trackers = أجهزة التعقب
settings-osc-vrchat-network-trackers-description = تبديل إرسال أجهزة تتبع محددة عبر أوه أس سي.
settings-osc-vrchat-network-trackers-chest = الصدر
settings-osc-vrchat-network-trackers-waist = الخصر
settings-osc-vrchat-network-trackers-hip = الورك
settings-osc-vrchat-network-trackers-knees = الركبتين
settings-osc-vrchat-network-trackers-feet = القدمين
settings-osc-vrchat-network-trackers-elbows = الكوعين
@@ -520,10 +526,6 @@ onboarding-reset_tutorial-description = هذه الميزة لم تنته بعد
## Setup start
onboarding-home = مرحبا بكم في سلايم في ار
# This cares about multilines and it's centered!!
onboarding-home-description =
جلب التعقب كامل الجسم
للجميع
onboarding-home-start = هيا نتجهز!
## Enter VR part of setup
@@ -572,6 +574,12 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = لقد قمت بتوصيل جميع أجهزة التعقب
## Tracker calibration tutorial
## Tracker assignment tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = العودة إلى بيانات اعتماد الواي فاي
@@ -581,12 +589,10 @@ 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 =
{ $trackers ->
{ $assigned ->
[zero] { $assigned } من { $trackers } أجهزة تعقب عينت
[one] جهاز واحد من { $trackers } أجهزة تعقب عينت
[two] جهازان من { $trackers } أجهزة تعقب عينت
[few] { $assigned } من { $trackers } أجهزة تعقب عينت
[many] { $assigned } من { $trackers } أجهزة تعقب عينت
*[other] { $assigned } من { $trackers } أجهزة تعقب عينت
}
onboarding-assign_trackers-advanced = إظهار مواقع التعيين المتقدمة
@@ -660,6 +666,18 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] تم تحديد الخصر، ولكنك تحتاج إلى تحديد جزء جسم غير معروف غير مخصص أيضًا!
}
## Tracker mounting method choose
onboarding-choose_mounting = ما طريقة معايرة التركيب المستخدمة؟
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
onboarding-manual_mounting-back = العودة إلى دخول في ار
@@ -689,6 +707,18 @@ onboarding-automatic_mounting-put_trackers_on-title = ارتدي أجهزة ال
onboarding-automatic_mounting-put_trackers_on-description = لمعايرة دوران التركيب، سنستخدم أجهزة التعقب التي قمت بتعيينها. ارتدي جميع أجهزة التعقب، يمكنك معرفة أي منها في المستند على اليمين.
onboarding-automatic_mounting-put_trackers_on-next = ارتديت جميع أجهزة التعقب.
## Tracker proportions method choose
onboarding-choose_proportions = ما هي طريقة معايرة النسب التي يجب استخدامها؟
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 = سيسمح لك بتعديل النسب يدويًا عن طريق تعديلها مباشرة
## Tracker manual proportions setup
onboarding-manual_proportions-back = العودة إلى برنامج تعليم إعادة التعيين
@@ -754,3 +784,6 @@ onboarding-automatic_proportions-done-description = اكتملت معايرة ن
## Home
home-no_trackers = لم يتم الكشف أو تعيين عن أي جهاز تعقب
## Status system

View File

@@ -0,0 +1,626 @@
### 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!
# 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 = Tilslutter til serveren
websocket-connection_lost = Forbindelse mistet til serveren. Forsøger at oprette forbindelse igen...
## Update notification
version_update-title = Ny version tilgængelig: { $version }
version_update-description = Ved at klikke på "Opdater" downloades SlimeVR-installationsprogrammet for dig.
version_update-update = Opdater
version_update-close = Luk
## Tips
tips-find_tracker = Ikke sikker på, hvilken tracker er hvilken? Ryst trackeren, og den vil fremhæve det tilsvarende element.
tips-do_not_move_heels = Sørg for, at dine hæle ikke bevæger sig under optagelsen!
tips-file_select = Træk og slip filer for at bruge, eller <u>gennemse</u>.
tips-tap_setup = Du kan trykke langsomt 2 gange på din tracker for at vælge den i stedet for at vælge den i menuen.
## Body parts
body_part-NONE = Ikke tildelt
body_part-HEAD = Hoved
body_part-NECK = Nakke
body_part-RIGHT_SHOULDER = Højre skulder
body_part-RIGHT_UPPER_ARM = Højre overarm
body_part-RIGHT_LOWER_ARM = Højre underarm
body_part-RIGHT_HAND = Højre hånd
body_part-RIGHT_UPPER_LEG = Højre lår
body_part-RIGHT_LOWER_LEG = Højre ankel
body_part-RIGHT_FOOT = Højre fod
body_part-CHEST = Bryst
body_part-WAIST = Talje
body_part-HIP = Hofte
body_part-LEFT_SHOULDER = Venstre skulder
body_part-LEFT_UPPER_ARM = Venstre overarm
body_part-LEFT_LOWER_ARM = Venstre underarm
body_part-LEFT_HAND = Venstre hånd
body_part-LEFT_UPPER_LEG = Venstre lår
body_part-LEFT_LOWER_LEG = Venstre ankel
body_part-LEFT_FOOT = Venstre fod
## Proportions
skeleton_bone-NONE = Ingen
skeleton_bone-HEAD = Hoved skift
skeleton_bone-NECK = Hals længde
skeleton_bone-torso_group = Torso Længde
skeleton_bone-CHEST = Bryst Længde
skeleton_bone-CHEST_OFFSET = Bryst Juster
skeleton_bone-WAIST = Taljelængde
skeleton_bone-HIP = Hoftelængde
skeleton_bone-HIP_OFFSET = Hofte Juster
skeleton_bone-HIPS_WIDTH = Hoftebredde
skeleton_bone-leg_group = Benlængde
skeleton_bone-UPPER_LEG = Øvre benlængde
skeleton_bone-LOWER_LEG = Underbenslængde
skeleton_bone-FOOT_LENGTH = Fodlængde
skeleton_bone-FOOT_SHIFT = Fodskift
skeleton_bone-SKELETON_OFFSET = Skelet Juster
skeleton_bone-SHOULDERS_DISTANCE = Skulder Afstand
skeleton_bone-SHOULDERS_WIDTH = Skulder Bredde
skeleton_bone-arm_group = Armlængde
skeleton_bone-UPPER_ARM = Overarmslængde
skeleton_bone-LOWER_ARM = Nedre armlængde
skeleton_bone-HAND_Y = Håndafstand Y
skeleton_bone-HAND_Z = Håndafstand Z
skeleton_bone-ELBOW_OFFSET = Albuer Juster
## Tracker reset buttons
reset-reset_all = Nulstil alle proportioner
reset-full = Fuld nulstilling
reset-mounting = Nulstil Montage
reset-yaw = Yaw Nulstil
## Serial detection stuff
serial_detection-new_device-p0 = Ny seriel enhed fundet!
serial_detection-new_device-p1 = Indtast dine Wi-Fi-legitimationsoplysninger!
serial_detection-new_device-p2 = Vælg venligst hvad du vil gøre med det
serial_detection-open_wifi = Opret forbindelse til Wi-Fi
serial_detection-open_serial = Åbn seriel konsol
serial_detection-submit = Indsend!
serial_detection-close = Tæt
## Navigation bar
navbar-home = Hjem
navbar-body_proportions = Kropsforhold
navbar-trackers_assign = Tracker opgave
navbar-mounting = Montage Kalibrering
navbar-onboarding = Opsætningsguide
navbar-settings = Indstillinger
## Bounding volume hierarchy recording
bvh-start_recording = Optag BVH
bvh-recording = Optager...
## Widget: Overlay settings
widget-overlay = Overlejring
widget-overlay-is_visible_label = Vis Overlejring i SteamVR
widget-overlay-is_mirrored_label = Vis Overlejring som Spejl
## Widget: Drift compensation
widget-drift_compensation-clear = Klar afdriftskompensation
## Widget: Developer settings
widget-developer_mode = Udviklertilstand
widget-developer_mode-high_contrast = Høj kontrast
widget-developer_mode-precise_rotation = Præcis rotation
widget-developer_mode-fast_data_feed = Hurtig datatilførsel
widget-developer_mode-filter_slimes_and_hmd = Filter slimes og HMD
widget-developer_mode-sort_by_name = Sorter efter navn
widget-developer_mode-raw_slime_rotation = Rå rotation
widget-developer_mode-more_info = Mere info
## Widget: IMU Visualizer
widget-imu_visualizer = Rotation
widget-imu_visualizer-rotation_raw = Rå
widget-imu_visualizer-rotation_preview = Forhåndsvisning
widget-imu_visualizer-rotation_hide = Skjul
## Tracker status
tracker-status-none = Ingen status
tracker-status-busy = Travl
tracker-status-error = Fejl
tracker-status-disconnected = Afbrudt
tracker-status-occluded = Okkluderet
tracker-status-ok = Okay
## Tracker status columns
tracker-table-column-name = Navn
tracker-table-column-type = Type
tracker-table-column-battery = Batteri
tracker-table-column-ping = Ping
tracker-table-column-tps = TPS
tracker-table-column-temperature = Temp. °C
tracker-table-column-linear-acceleration = Accel. X/Y/Z
tracker-table-column-rotation = Rotation X/Y/Z
tracker-table-column-position = Position X/Y/Z
tracker-table-column-url = URL
## Tracker rotation
tracker-rotation-front = Forrest
tracker-rotation-left = Venstre
tracker-rotation-right = Højre
tracker-rotation-back = Tilbage
## Tracker information
tracker-infos-manufacturer = Fabrikant
tracker-infos-display_name = Display navn
tracker-infos-custom_name = Brugerdefineret navn
tracker-infos-url = Tracker URL
tracker-infos-version = Firmware Version
tracker-infos-hardware_rev = Hardware Revision
tracker-infos-hardware_identifier = Hardware ID
tracker-infos-imu = IMU-sensor
## Tracker settings
tracker-settings-back = Gå tilbage til trackerlisten
tracker-settings-title = Tracker indstillinger
tracker-settings-assignment_section = Opgave
tracker-settings-assignment_section-description = Hvilken del af kroppen trackeren er tildelt.
tracker-settings-assignment_section-edit = Rediger opgave
tracker-settings-mounting_section = Monteringsposition
tracker-settings-mounting_section-description = Hvor er trackeren monteret?
tracker-settings-mounting_section-edit = Rediger montering
tracker-settings-drift_compensation_section = Tillad afdriftskompensation
tracker-settings-drift_compensation_section-description = Skal denne tracker kompensere for dens drift, når driftkompensation er aktiveret?
tracker-settings-drift_compensation_section-edit = Tillad afdriftskompensation
# 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 navn
tracker-settings-name_section-description = Giv den et sødt kælenavn :)
tracker-settings-name_section-placeholder = NightyBeast's venstre ben
## Tracker part card info
tracker-part_card-no_name = Intet navn
tracker-part_card-unassigned = Ikke tildelt
## Body assignment menu
body_assignment_menu = Hvor vil du have denne tracker til at være?
body_assignment_menu-description = Vælg en placering, hvor du ønsker, at denne tracker skal tildeles. Alternativt kan du vælge at administrere alle trackere på én gang i stedet for én efter én.
body_assignment_menu-show_advanced_locations = Vis avancerede placeringer
body_assignment_menu-manage_trackers = Administrer alle trackere
body_assignment_menu-unassign_tracker = Fjern tildeling af 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 = Hvilken tracker skal tildeles til din
tracker_selection_menu-NONE = Hvilken tracker vil du fjerne tildelingen af?
tracker_selection_menu-HEAD = { -tracker_selection-part } hoved?
tracker_selection_menu-NECK = { -tracker_selection-part } hals?
tracker_selection_menu-RIGHT_SHOULDER = { -tracker_selection-part } højre skulder?
tracker_selection_menu-RIGHT_UPPER_ARM = { -tracker_selection-part } højre overarm?
tracker_selection_menu-RIGHT_LOWER_ARM = { -tracker_selection-part } højre underarm?
tracker_selection_menu-RIGHT_HAND = { -tracker_selection-part } højre hånd?
tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } højre lår?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } højre ankel?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } højre fod?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } højre controller?
tracker_selection_menu-CHEST = { -tracker_selection-part } brystet?
tracker_selection_menu-WAIST = { -tracker_selection-part } talje?
tracker_selection_menu-HIP = { -tracker_selection-part } hofte?
tracker_selection_menu-LEFT_SHOULDER = { -tracker_selection-part } venstre skulder?
tracker_selection_menu-LEFT_UPPER_ARM = { -tracker_selection-part } venstre overarm?
tracker_selection_menu-LEFT_LOWER_ARM = { -tracker_selection-part } venstre underarm?
tracker_selection_menu-LEFT_HAND = { -tracker_selection-part } venstre hånd?
tracker_selection_menu-LEFT_UPPER_LEG = { -tracker_selection-part } venstre lår?
tracker_selection_menu-LEFT_LOWER_LEG = { -tracker_selection-part } venstre ankel?
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } venstre fod?
tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part } venstre controller?
tracker_selection_menu-unassigned = Ikke-tildelte trackere
tracker_selection_menu-assigned = Tildelte trackere
tracker_selection_menu-dont_assign = Tildel ikke
# This line cares about multilines.
# <b>text</b> means that the text should be bold.
tracker_selection_menu-neck_warning =
<b>Advarsel:</b> En halstracker kan være dødbringende, hvis den justeres for stramt,
Remmen kunne fjerne blodcirkulationen til dit hoved!
tracker_selection_menu-neck_warning-done = Jeg forstår risiciene
tracker_selection_menu-neck_warning-cancel = Annuller
## Mounting menu
mounting_selection_menu = Hvor vil du have denne tracker til at være?
mounting_selection_menu-close = Luk
## Sidebar settings
settings-sidebar-title = Indstillinger
settings-sidebar-general = Generel
settings-sidebar-tracker_mechanics = Tracker mekanik
settings-sidebar-fk_settings = Tracking indstillinger
settings-sidebar-interface = Brugergrænseflade
settings-sidebar-osc_router = OSC-router
settings-sidebar-osc_trackers = VRChat OSC trackere
settings-sidebar-utils = Hjælpeprogrammer
settings-sidebar-serial = Seriel konsol
## SteamVR settings
settings-general-steamvr = SteamVR
settings-general-steamvr-subtitle = SteamVR-trackere
# 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 =
Aktivér eller deaktiver specifikke SteamVR-trackere.
Nyttig til spil eller apps, der kun understøtter bestemte trackere.
settings-general-steamvr-trackers-waist = Talje
settings-general-steamvr-trackers-chest = Bryst
settings-general-steamvr-trackers-feet = Fødder
settings-general-steamvr-trackers-knees = Knæ
settings-general-steamvr-trackers-elbows = Albuer
settings-general-steamvr-trackers-hands = Hænder
## Tracker mechanics
settings-general-tracker_mechanics-filtering = Filtrering
# This also cares about multilines
settings-general-tracker_mechanics-filtering-description =
Vælg filtreringstypen for dine trackere.
Forudsigelse forudsiger bevægelse, mens udjævning udjævner bevægelse.
settings-general-tracker_mechanics-filtering-type = Filtrerings type
settings-general-tracker_mechanics-filtering-type-none = Ingen filtrering
settings-general-tracker_mechanics-filtering-type-none-description = Brug rotationer, som de er. Vil ikke foretage nogen filtrering.
settings-general-tracker_mechanics-filtering-type-smoothing = Udjævning
settings-general-tracker_mechanics-filtering-type-smoothing-description = Udjævner bevægelser, men tilføjer en smule latens.
settings-general-tracker_mechanics-filtering-type-prediction = Forudsigelse
settings-general-tracker_mechanics-filtering-type-prediction-description = Reducerer latens og gør bevægelser hutigere, men kan forårsage rystelser.
settings-general-tracker_mechanics-filtering-amount = Mængde
settings-general-tracker_mechanics-drift_compensation = Drift kompensation
# This cares about multilines
settings-general-tracker_mechanics-drift_compensation-description =
Kompenserer IMU yaw drift ved at anvende en omvendt rotation.
Skift kompensationsbeløb og hvor mange nulstillinger der skal tages i betragtning.
settings-general-tracker_mechanics-drift_compensation-enabled-label = Drift kompensation
settings-general-tracker_mechanics-drift_compensation-amount-label = Kompensationsmængde
settings-general-tracker_mechanics-drift_compensation-max_resets-label = Brug op til x seneste nulstillinger
## FK/Tracking settings
settings-general-fk_settings = Trackingsindstillinger
# 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 = Skate korrektion
settings-general-fk_settings-leg_tweak-toe_snap = Tå snap
settings-general-fk_settings-leg_tweak-skating_correction-amount = Skate korrektionsstyrke
settings-general-fk_settings-leg_tweak-skating_correction-description = Skate-korrektion korrigerer for skate, men kan reducere nøjagtigheden i visse bevægelsesmønstre. Når du aktiverer dette, skal du sørge for at nulstille og kalibrere i spillet.
settings-general-fk_settings-leg_tweak-floor_clip-description = Floor-clip kan reducere eller endda eliminere klipning gennem gulvet. Når du aktiverer dette, skal du sørge for at nulstille og kalibrere i spillet.
settings-general-fk_settings-leg_tweak-toe_snap-description = Tå-snap forsøger at gætte rotationen af dine fødder, hvis fodtrackere ikke er i brug.
settings-general-fk_settings-leg_tweak-foot_plant-description = Foot-plant roterer dine fødder så de er parallelle med jorden, når de er i kontakt med jorden.
settings-general-fk_settings-leg_fk = Bensporing
settings-general-fk_settings-arm_fk = Arm sporing
settings-general-fk_settings-arm_fk-description = Tving arme til spore fra HMD, selvom positionshånddata er tilgængelige.
settings-general-fk_settings-arm_fk-force_arms = Tving arme fra HMD
settings-general-fk_settings-skeleton_settings = Indstillinger for skelet
settings-general-fk_settings-skeleton_settings-description = Slå skeletindstillinger til eller fra. Det anbefales at lade disse være på.
settings-general-fk_settings-skeleton_settings-extended_spine = Udvidet rygsøjle
settings-general-fk_settings-skeleton_settings-extended_pelvis = Forlænget pelvis
settings-general-fk_settings-skeleton_settings-extended_knees = Forlænget knæ
settings-general-fk_settings-vive_emulation-title = Vive emulering
settings-general-fk_settings-vive_emulation-description = Emuler de taljetrackerproblemer, som Vive-trackere har. Dette er en joke og gør sporing værre.
settings-general-fk_settings-vive_emulation-label = Aktivér Vive-emulering
## Gesture control settings (tracker tapping)
settings-general-gesture_control-subtitle = Tryk baseret nulstilling
# 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] tryk
*[other] tryk
}
settings-general-gesture_control-yawResetEnabled = Aktivér tryk for at yaw resette
## Interface settings
settings-general-interface = Brugergrænseflade
settings-general-interface-dev_mode = Udvikler-tilstand
settings-general-interface-dev_mode-description = Denne tilstand kan være nyttig, hvis du har brug for dybdegående data eller for at interagere med tilsluttede trackere på et mere avanceret niveau.
settings-general-interface-dev_mode-label = Udvikler-tilstand
settings-general-interface-serial_detection = Seriel enhedsregistrering
settings-general-interface-serial_detection-description = Denne mulighed viser en pop-up, hver gang du tilslutter en ny seriel enhed, der kan være en tracker. Det hjælper med at forbedre opsætningsprocessen for en tracker.
settings-general-interface-serial_detection-label = Seriel enhedsregistrering
settings-general-interface-feedback_sound = Feedback lyd
settings-general-interface-feedback_sound-description = Denne indstilling afspiller en lyd, når du nulstiller
settings-general-interface-feedback_sound-label = Feedback lyd
settings-general-interface-feedback_sound-volume = Feedback lydstyrke
settings-general-interface-theme = Farvetema
settings-general-interface-lang = Vælg sprog
settings-general-interface-lang-description = Skift det standardsprog, du vil bruge.
settings-general-interface-lang-placeholder = Vælg det sprog, der skal bruges
## Serial settings
settings-serial = Seriel konsol
settings-serial-connection_lost = Forbindelse til seriel mistet, Genopretter forbindelse...
settings-serial-reboot = Genstart
settings-serial-factory_reset = Nulstil til fabriksindstillinger
# This cares about multilines
# <b>text</b> means that the text should be bold
settings-serial-factory_reset-warning =
<b>Advarsel:</b> Dette nulstiller trackeren til fabriksindstillingerne.
Hvilket betyder, at alle Wi-Fi- og kalibreringsindstillinger <b>går tabt!</b>
settings-serial-factory_reset-warning-ok = Jeg ved hvad jeg laver
settings-serial-factory_reset-warning-cancel = Annuller
settings-serial-get_infos = Hent oplysninger
settings-serial-serial_select = Vælg en seriel port
settings-serial-auto_dropdown_item = Auto
## OSC router settings
settings-osc-router = OSC-router
# This cares about multilines
settings-osc-router-description =
Videresend OSC-meddelelser fra et andet program.
Nyttig til brug af et andet OSC-program med VRChat, for eksempel.
settings-osc-router-enable = Aktiver
settings-osc-router-enable-label = Aktiver
settings-osc-router-network = Netværksporte
# This cares about multilines
settings-osc-router-network-description =
Vælg de porte der skal bruges til at lytte og sende data.
Disse kan være de samme som de andre porte der bruges på SlimeVR-serveren.
settings-osc-router-network-port_in =
.label = Port ind
.placeholder = Port ind (standard: 9002)
settings-osc-router-network-port_out =
.label = Port ud
.placeholder = Port ud (standard: 9000)
settings-osc-router-network-address = Netværksadresse
settings-osc-router-network-address-description = Indstil den adresse, der skal sendes data på.
settings-osc-router-network-address-placeholder = IPV4-adresse
## OSC VRChat settings
settings-osc-vrchat = VRChat OSC trackere
# This cares about multilines
settings-osc-vrchat-description =
Skift VRChat-specifikke indstillinger for at modtage HMD-data og sende
trackerdata til FBT uden SteamVR (f.eks. Quest standalone).
settings-osc-vrchat-enable = Aktiver
settings-osc-vrchat-enable-label = Aktiver
settings-osc-vrchat-network = Netværksporte
settings-osc-vrchat-network-description = Indstil portene til at lytte og sende data til VRChat.
settings-osc-vrchat-network-port_in =
.label = Port ind
.placeholder = Port ind (standard: 9001)
settings-osc-vrchat-network-port_out =
.label = Port ud
.placeholder = Port ud (standard: 9000)
settings-osc-vrchat-network-address = Netværksadresse
settings-osc-vrchat-network-address-description = Vælg hvilken adresse der skal sende data til VRChat (tjek dine Wi-Fi-indstillinger på din enhed).
settings-osc-vrchat-network-address-placeholder = VRChat ip-adresse
settings-osc-vrchat-network-trackers = Trackere
settings-osc-vrchat-network-trackers-description = Skift afsendelse af specifikke trackere via OSC.
settings-osc-vrchat-network-trackers-chest = Bryst
settings-osc-vrchat-network-trackers-hip = Hofte
settings-osc-vrchat-network-trackers-knees = Knæ
settings-osc-vrchat-network-trackers-feet = Fødder
settings-osc-vrchat-network-trackers-elbows = Albuer
## VMC OSC settings
settings-osc-vmc = Virtual Motion Capture
# This cares about multilines
settings-osc-vmc-description =
Skift indstillinger, der er specifikke for VMC-protokollen (Virtual Motion Capture)
for at sende SlimeVRs data og modtage data fra andre apps.
settings-osc-vmc-enable = Aktiver
settings-osc-vmc-enable-description = Skift afsendelse og modtagelse af data.
settings-osc-vmc-enable-label = Aktiver
settings-osc-vmc-network = Netværksporte
settings-osc-vmc-network-description = Vælg portene til at lytte og sende data via VMC
settings-osc-vmc-network-port_in =
.label = Port ind
.placeholder = Port ind (standard: 39540)
settings-osc-vmc-network-port_out =
.label = Port ud
.placeholder = Port ud (standard: 39539)
settings-osc-vmc-network-address = Netværksadresse
settings-osc-vmc-network-address-description = Vælg hvilken adresse du vil sende data på via VMC
settings-osc-vmc-network-address-placeholder = IPV4-adresse
settings-osc-vmc-vrm = VRM-model
settings-osc-vmc-vrm-description = Indlæs en VRM-model for at tillade hovedanker og muliggøre en højere kompatibilitet med andre applikationer
settings-osc-vmc-vrm-model_unloaded = Ingen model indlæst
settings-osc-vmc-vrm-file_select = Træk og slip en model, du vil bruge, eller <u>gennemse</u>
## Setup/onboarding menu
onboarding-skip = Spring opsætning over
onboarding-continue = Fortsæt
onboarding-previous_step = Forrige trin
onboarding-setup_warning =
<b>Advarsel:</b> Den indledende opsætning er nødvendig for god tracking,
det er nødvendigt, hvis det er første gang, du bruger SlimeVR.
onboarding-setup_warning-skip = Spring opsætning over
onboarding-setup_warning-cancel = Fortsæt konfigurationen
## Wi-Fi setup
onboarding-wifi_creds-back = Gå tilbage til introduktion
onboarding-wifi_creds = Indtast Wi-Fi-oplysninger
# This cares about multilines
onboarding-wifi_creds-description =
Trackerne bruger disse oplysninger til at oprette forbindelse trådløst.
Brug de oplysninger, du i øjeblikket har forbindelse til.
onboarding-wifi_creds-skip = Spring Wi-Fi-indstillinger over
onboarding-wifi_creds-submit = Færdig!
onboarding-wifi_creds-ssid =
.label = Wi-Fi-navn
.placeholder = Indtast Wi-Fi-navn
onboarding-wifi_creds-password =
.label = Kodeord
.placeholder = Indtast Wi-Fi-kodeord
## Mounting setup
onboarding-reset_tutorial-back = Gå tilbage til monteringskalibrering
onboarding-reset_tutorial = Start forfra
onboarding-reset_tutorial-description = Denne funktion er ikke færdig, bare tryk på fortsæt
## Setup start
onboarding-home = Velkommen til SlimeVR
onboarding-home-start = Lad os komme i gang!
## Enter VR part of setup
onboarding-enter_vr-back = Gå tilbage til Tracker-tildeler
onboarding-enter_vr-title = Tid til at gå ind i VR!
onboarding-enter_vr-description = Tag alle dine trackere på, og gå derefter på VR!
onboarding-enter_vr-ready = Jeg er klar
## Setup done
onboarding-done-title = Du er klar!
onboarding-done-description = Nyd din full-body oplevelse
onboarding-done-close = Luk opsætning
## Tracker connection setup
onboarding-connect_tracker-back = Gå tilbage til Wi-Fi-oplysninger
onboarding-connect_tracker-title = Tilslut trackere
onboarding-connect_tracker-description-p0 = Nu til den sjove del, forbind alle trackere!
onboarding-connect_tracker-description-p1 = Du skal blot tilslutte alle, der ikke er tilsluttet endnu, via en USB-port.
onboarding-connect_tracker-issue-serial = Jeg har problemer med at oprette forbindelse!
onboarding-connect_tracker-usb = USB-tracker
onboarding-connect_tracker-connection_status-none = Leder efter trackere
onboarding-connect_tracker-connection_status-serial_init = Tilslutter seriel enhed
onboarding-connect_tracker-connection_status-provisioning = Sender Wi-Fi-oplysninger
onboarding-connect_tracker-connection_status-connecting = Forsøger at oprette forbindelse til Wi-Fi
onboarding-connect_tracker-connection_status-looking_for_server = Leder efter server
onboarding-connect_tracker-connection_status-connection_error = Kan ikke oprette forbindelse til Wi-Fi
onboarding-connect_tracker-connection_status-could_not_find_server = Kunne ikke finde serveren
onboarding-connect_tracker-connection_status-done = Tilsluttet serveren
# $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] Ingen trackere tilsluttet
[one] En tracker tilsluttet
*[other] { $amount } trackere tilsluttet
}
onboarding-connect_tracker-next = Jeg har tilsluttet alle mine trackere
## Tracker calibration tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = Gå tilbage til Wi-Fi-oplysninger
onboarding-assign_trackers-title = Tildel trackere
onboarding-assign_trackers-description = Lad os vælge, hvilken tracker der skal hvorhen. Klik på et sted, hvor du vil placere en tracker
# 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 } af en tracker tildelt
*[other] { $assigned } af { $trackers } trackere tildelt
}
onboarding-assign_trackers-advanced = Vis avancerede trackerplaceringer
onboarding-assign_trackers-next = Jeg har tildelt alle trackerene
## Tracker assignment warnings
## Tracker mounting method choose
onboarding-choose_mounting = Hvilken monteringskalibreringsmetode vil du bruge?
onboarding-choose_mounting-auto_mounting = Automatisk montering
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Anbefalet
onboarding-choose_mounting-auto_mounting-description = Dette registrerer automatisk monteringsretningerne til alle dine trackere fra 2 stillinger
onboarding-choose_mounting-manual_mounting = Manuel montering
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Hvis du ved hvad du laver
onboarding-choose_mounting-manual_mounting-description = Dette giver dig mulighed for manuelt at vælge monteringsretningen for hver tracker
## Tracker manual mounting setup
onboarding-manual_mounting = Manuel montering
onboarding-manual_mounting-description = Klik på hver tracker og vælg hvilken vej de er monteret
onboarding-manual_mounting-auto_mounting = Automatisk montering
onboarding-manual_mounting-next = Næste trin
## Tracker automatic mounting setup
onboarding-automatic_mounting-next = Næste trin
onboarding-automatic_mounting-prev_step = Forrige trin
onboarding-automatic_mounting-done-restart = Prøv igen
onboarding-automatic_mounting-mounting_reset-step-0 = 1. Sæt dig på hug i en "skiløb" -stilling med bøjede ben, din overkrop vippet fremad og dine arme bøjet.
onboarding-automatic_mounting-preparation-title = Forberedelse
onboarding-automatic_mounting-put_trackers_on-title = Tag dine trackere på
onboarding-automatic_mounting-put_trackers_on-description = For at kalibrere rotationer bruger vi de trackere, du lige har tildelt. Tag alle dine trackere på du kan se hvilke der er hvilke i figuren til højre.
onboarding-automatic_mounting-put_trackers_on-next = Jeg har alle mine trackere på
## Tracker proportions method choose
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Anbefalet
## Tracker manual proportions setup
## Tracker automatic proportions setup
onboarding-automatic_proportions-requirements-next = Jeg har læst kravene
onboarding-automatic_proportions-start_recording-next = Start optagelse
onboarding-automatic_proportions-recording-description-p0 = Optagelse i gang...
onboarding-automatic_proportions-recording-description-p1 = Foretag de bevægelser, der er vist nedenfor:
onboarding-automatic_proportions-recording-processing = Behandler resultatet
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =
{ $time ->
[one] { $time } sekund tilbage
*[other] { $time } sekunder tilbage
}
onboarding-automatic_proportions-verify_results-title = Bekræft resultater
onboarding-automatic_proportions-verify_results-description = Tjek resultaterne nedenfor, ser de korrekte ud?
onboarding-automatic_proportions-verify_results-processing = Behandler resultatet
onboarding-automatic_proportions-verify_results-redo = prøv igen
onboarding-automatic_proportions-done-title = Krop målt og gemt.
onboarding-automatic_proportions-done-description = Kalibreringen af dine kropsproportioner er fuldført!
## Home
home-no_trackers = Ingen trackere registreret eller tildelt

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 = Verbindung zum Server wird hergestellt...
websocket-connection_lost = Verbindung zum Server verloren. Versuche Verbindung wiederherzustellen ...
## Update notification
version_update-title = Neue Version verfügbar: { $version }
version_update-description = Wenn Sie auf "Aktualisieren" klicken, wird der SlimeVR-Installationsassistent für dich heruntergeladen.
version_update-update = Aktualisieren
version_update-close = Schließen
## Tips
tips-find_tracker = Sie sind sich nicht sicher, welcher Tracker welcher ist? Schütteln Sie einen Tracker, um den zugehörigen Eintrag hervorzuheben.
tips-do_not_move_heels = Stellen Sie sicher, dass Sie Ihre Fersen während der Aufnahme nicht bewegen!
tips-file_select = Dateien per Drag & Drop verwenden oder <u>durchsuchen</u>
tips-tap_setup = Sie können langsam 2 Mal auf Ihren Tracker tippen, um ihn auszuwählen, anstatt ihn aus dem Menü auszuwählen.
## Body parts
@@ -74,6 +79,7 @@ skeleton_bone-ELBOW_OFFSET = Ellbogenversatz
reset-reset_all = Alle Proportionen zurücksetzen
reset-full = Reset
reset-mounting = Befestigungs-Reset
reset-yaw = Horizontaler Reset
## Serial detection stuff
@@ -94,11 +100,16 @@ navbar-mounting = Tracker-Ausrichtung
navbar-onboarding = Einrichtungs-Assistent
navbar-settings = Einstellungen
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = BVH aufnehmen
bvh-recording = Aufnahme läuft...
## Tracking pause
tracking-unpaused = Tracking pausieren
tracking-paused = Tracking fortsetzen
## Widget: Overlay settings
widget-overlay = Visualisierung
@@ -125,6 +136,7 @@ widget-developer_mode-more_info = Mehr Infos
widget-imu_visualizer = Drehung
widget-imu_visualizer-rotation_raw = Rohe Drehung
widget-imu_visualizer-rotation_preview = Vorschau
widget-imu_visualizer-rotation_hide = Ausblenden
## Tracker status
@@ -163,6 +175,9 @@ tracker-infos-custom_name = Benutzerdefinierter Name
tracker-infos-url = Tracker-Adresse
tracker-infos-version = Firmware-Version
tracker-infos-hardware_rev = Hardware-Version
tracker-infos-hardware_identifier = Hardware-ID
tracker-infos-imu = IMU-Sensor
tracker-infos-board_type = Platine
## Tracker settings
@@ -224,7 +239,7 @@ tracker_selection_menu-LEFT_LOWER_ARM = { -tracker_selection-part } dem linken U
tracker_selection_menu-LEFT_HAND = { -tracker_selection-part } der linken Hand zugewiesen werden?
tracker_selection_menu-LEFT_UPPER_LEG = { -tracker_selection-part } dem linken Oberschenkel zugewiesen werden?
tracker_selection_menu-LEFT_LOWER_LEG = { -tracker_selection-part } dem linken Unterschenkel zugewiesen werden?
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } dem Linken Fuß zugewiesen zugewiesen werden?
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } dem linken Fuß zugewiesen zugewiesen werden?
tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part } dem linken Controller zugewiesen werden?
tracker_selection_menu-unassigned = Nicht zugewiesene Tracker
tracker_selection_menu-assigned = Zugewiesene Tracker
@@ -251,6 +266,7 @@ settings-sidebar-fk_settings = FK-Einstellungen
settings-sidebar-gesture_control = Gestensteuerung
settings-sidebar-interface = Bedienoberfläche
settings-sidebar-osc_router = OSC-Router
settings-sidebar-osc_trackers = VRChat OSC-Tracker
settings-sidebar-utils = Werkzeuge
settings-sidebar-serial = Serielle Konsole
@@ -309,8 +325,13 @@ settings-general-fk_settings-leg_tweak-floor_clip = Bodenclip
# 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 = 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_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.
@@ -336,6 +357,12 @@ settings-general-gesture_control-taps =
[one] 1-mal antippen
*[other] { $amount }-mal antippen
}
settings-general-gesture_control-yawResetEnabled = Horizontaler Reset durch Antippen
settings-general-gesture_control-yawResetDelay = Verzögerung für einen horizontalen Reset
settings-general-gesture_control-yawResetTaps = Antipp-Anzahl für einen horizontalen Reset
settings-general-gesture_control-fullResetEnabled = Vollständiger Reset durch Antippen
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-mountingResetTaps = Anzahl für Befestigungs-Reset
@@ -353,6 +380,7 @@ settings-general-interface-feedback_sound = Feedback-Geräusch
settings-general-interface-feedback_sound-description = Diese Option wird ein Geräusch abspielen, wenn ein Reset ausgeführt wurde.
settings-general-interface-feedback_sound-label = Feedback-Geräusch
settings-general-interface-feedback_sound-volume = Feedback-Sound-Lautstärke
settings-general-interface-theme = Farbschema
settings-general-interface-lang = Sprachauswahl
settings-general-interface-lang-description = Ändern Sie die Standard-Sprache, die Sie verwenden möchten
settings-general-interface-lang-placeholder = Wählen Sie die zu verwendende Sprache aus
@@ -425,7 +453,7 @@ settings-osc-vrchat-network-address-placeholder = VRChat-IP-Adresse
settings-osc-vrchat-network-trackers = Tracker
settings-osc-vrchat-network-trackers-description = Ein- und Ausschalten des Sendens und Empfangens von Daten
settings-osc-vrchat-network-trackers-chest = Brust
settings-osc-vrchat-network-trackers-waist = Taille
settings-osc-vrchat-network-trackers-hip = Hüfte
settings-osc-vrchat-network-trackers-knees = Knie
settings-osc-vrchat-network-trackers-feet = Füße
settings-osc-vrchat-network-trackers-elbows = Ellbogen
@@ -433,6 +461,8 @@ settings-osc-vrchat-network-trackers-elbows = Ellbogen
## VMC OSC settings
settings-osc-vmc = Virtual Motion Capture
# This cares about multilines
settings-osc-vmc-description = Einstellungsänderungen spezifisch für das VMC-Protokoll (Virtual Motion Capture Protocol), um die Skelett-Daten von SlimeVR zu senden und Skelett-Daten von anderen Applikationen zu empfangen.
settings-osc-vmc-enable = Aktivieren
settings-osc-vmc-enable-description = Ein- und Ausschalten des Sendens und Empfangen von Daten.
settings-osc-vmc-enable-label = Aktivieren
@@ -457,6 +487,7 @@ settings-osc-vmc-vrm-model_loaded =
}
settings-osc-vmc-vrm-file_select = Modell per Drag & Drop laden oder <u>durchsuchen</u>
settings-osc-vmc-anchor_hip = Hüftenverankerung
settings-osc-vmc-anchor_hip-description = Die Hüften-Verankerung für das Tracking ist nützlich für VTubing im Sitzen. Beim Deaktivieren muss ein VRM-Model geladen werden.
settings-osc-vmc-anchor_hip-label = Hüftenverankerung
## Setup/onboarding menu
@@ -464,6 +495,10 @@ settings-osc-vmc-anchor_hip-label = Hüftenverankerung
onboarding-skip = Einrichtung überspringen
onboarding-continue = Fortsetzen
onboarding-wip = Noch in Bearbeitung
onboarding-previous_step = Vorheriger Schritt
onboarding-setup_warning = <b>Warnung:</b> Für gutes Tracking ist die Ersteinrichtung erforderlich! Bei der ersten Benutzung dies benötigt.
onboarding-setup_warning-skip = Einrichtung überspringen
onboarding-setup_warning-cancel = Einrichtung fortsetzen
## Wi-Fi setup
@@ -488,14 +523,22 @@ 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-skip = Schritt überspringen
# Cares about multiline
onboarding-reset_tutorial-0 =
Tippen Sie { $taps } mal auf den markierten Tracker, um den horizontalen Reset auszulösen.
Dadurch zeigen die Tracker in die gleiche Richtung wie Ihre VR-Brille.
# Cares about multiline
onboarding-reset_tutorial-1 =
Tippen Sie { $taps } mal auf den markierten Tracker, um einen vollständigen Reset auszulösen.
Sie müssen dafür in einer I-Pose stehen. Es gibt eine Verzögerung von 3 Sekunden (konfigurierbar), bevor der Reset tatsächlich durchgeführt wird.
Dadurch werden die Position und Rotation aller Ihrer Tracker vollständig zurückgesetzt. Dies sollte die meisten Probleme beheben.
## Setup start
onboarding-home = Willkommen zu SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
VR-Fullbody Tracking
für alle
onboarding-home-start = Los gehts!
## Enter VR part of setup
@@ -540,6 +583,26 @@ onboarding-connect_tracker-connected_trackers =
} verbunden
onboarding-connect_tracker-next = Ich habe alle meine Tracker verbunden.
## Tracker calibration tutorial
onboarding-calibration_tutorial = IMU-Kalibrierungs-Tutorial
onboarding-calibration_tutorial-subtitle = Dies wird dazu beitragen, das Driften der Tracker zu reduzieren!
onboarding-calibration_tutorial-description = Jedes Mal, wenn Sie Ihre Tracker einschalten, müssen diese für einen Moment auf einer ebenen Oberfläche ruhen, um sie zu kalibrieren. Lassen Sie uns dies nun tun, indem Sie auf die Schaltfläche "Kalibrieren" klicken. <b>Verschieben Sie die Tracker nicht!</b>
onboarding-calibration_tutorial-calibrate = Ich habe meine Tracker auf den Tisch gelegt
onboarding-calibration_tutorial-status-waiting = Wir warten auf Sie
onboarding-calibration_tutorial-status-calibrating = Kalibriere
onboarding-calibration_tutorial-status-success = Gut!
onboarding-calibration_tutorial-status-error = Der Tracker wurde bewegt
## Tracker assignment tutorial
onboarding-assignment_tutorial = So bereiten Sie einen SlimeVR-Tracker vor, bevor Sie diesen anlegen
onboarding-assignment_tutorial-first_step = 1. Platzieren Sie einen Körperteilaufkleber (falls vorhanden) auf dem Tracker Ihrer Wahl
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Aufkleber
onboarding-assignment_tutorial-second_step-continuation = Die Klettseite für die Verlängerung sollte in dieser Ausrichtung sein:
onboarding-assignment_tutorial-done = Ich habe Aufkleber und Bänder angebracht!
## Tracker assignment setup
onboarding-assign_trackers-back = Zurück zu den WLAN-Zugangsdaten
@@ -572,6 +635,34 @@ onboarding-assign_trackers-warning-LEFT_FOOT =
*[other] Der linke Fuß ist zugewiesen, aber "Unbekanntes nicht zugewiesenes Körperteil" muss ebenfalls zugewiesen sein!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_FOOT =
{ $unassigned ->
[0] Der rechte Fuß ist zugewiesen, aber der rechte Unter- und Oberschenkel und entweder die Brust, die Hüfte oder die Taille müssen ebenfalls zugewiesen werden!
[1] Der rechte Fuß ist zugewiesen, aber der rechte Oberschenkel und entweder die Brust, die Hüfte oder die Taille müssen ebenfalls zugewiesen werden!
[2] Der rechte Fuß ist zugewiesen, aber der rechte Unterschenkel und entweder die Brust, die Hüfte oder die Taille müssen ebenfalls zugewiesen werden!
[3] Der rechte Fuß ist zugewiesen, aber entweder die Brust, die Hüfte oder die Taille muss ebenfalls zugewiesen werden!
[4] Der rechte Fuß ist zugewiesen, aber der rechte Unter- und Oberschenkel müssen ebenfalls zugewiesen werden!
[5] Der rechte Fuß ist zugewiesen, aber der rechte Oberschenkel muss ebenfalls zugewiesen werden!
[6] Der rechte Fuß ist zugewiesen, aber der rechte Unterschenkel muss ebenfalls zugewiesen werden!
*[other] Der rechte Fuß ist zugewiesen, aber "Unbekanntes nicht zugewiesenes Körperteil" muss ebenfalls zugewiesen werden!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_LOWER_LEG =
{ $unassigned ->
[0] Der linke Unterschenkel ist zugewiesen, aber der linke Oberschenkel und entweder die Brust, die Hüfte oder die Taille muss ebenfalls zugewiesen werden!
[1] Der linke Unterschenkel ist zugewiesen, aber entweder die Brust, die Hüfte oder die Taille muss ebenfalls zugewiesen werden!
[2] Der linke Unterschenkel ist zugewiesen, aber der linke Oberschenkel muss ebenfalls zugewiesen werden!
*[other] Der linke Unterschenkel ist zugewiesen, aber "Unbekanntes nicht zugewiesenes Körperteil" muss ebenfalls zugewiesen werden!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_LOWER_LEG =
{ $unassigned ->
[0] Der rechte Unterschenkel ist zugewiesen, aber der rechte Oberschenkel und entweder die Brust, die Hüfte oder die Taille muss ebenfalls zugewiesen werden!
[1] Der rechte Unterschenkel ist zugewiesen, aber entweder die Brust, die Hüfte oder die Taille muss ebenfalls zugewiesen werden!
[2] Der rechte Unterschenkel ist zugewiesen, aber der rechte Oberschenkel muss ebenfalls zugewiesen werden!
*[other] Der rechte Unterschenkel ist zugewiesen, aber "Unbekanntes nicht zugewiesenes Körperteil" muss ebenfalls zugewiesen werden!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_UPPER_LEG =
{ $unassigned ->
[0] Der linke Oberschenkel ist zugewiesen, aber entweder die Brust, die Hüfte oder die Taille muss ebenfalls zugewiesen werden!
@@ -596,6 +687,20 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] Taille ist zugewiesen, aber "Unbekanntes nicht zugewiesenes Körperteil" muss ebenfalls zugewiesen werden!
}
## Tracker mounting method choose
onboarding-choose_mounting = Welche Kalibrierungsmethode ist zu verwenden?
# Multiline text
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-manual_mounting = Manuelle Befestigungsposition
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Wenn du weißt, was du tust
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
onboarding-manual_mounting-back = Zurück zum Eintritt in VR
@@ -625,6 +730,18 @@ onboarding-automatic_mounting-put_trackers_on-title = Legen Sie Ihre Tracker an
onboarding-automatic_mounting-put_trackers_on-description = Um die Drehung der Tracker zu kalibrieren, werden die Tracker verwendet, welche Sie gerade zugewiesen haben. Ziehen Sie alle Ihre Tracker an, in der Abbildung rechts können sie sehen um welchen Tracker es sich handelt.
onboarding-automatic_mounting-put_trackers_on-next = Ich habe alle meine Tracker angelegt
## Tracker proportions method choose
onboarding-choose_proportions = Welche Kalibrierungsmethode ist zu verwenden?
onboarding-choose_proportions-auto_proportions = Automatische Proportionen
# Italized text
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-file_type = Körperproportions-Datei
## Tracker manual proportions setup
onboarding-manual_proportions-back = Gehen Sie zurück zum Reset-Tutorial
@@ -669,3 +786,13 @@ onboarding-automatic_proportions-done-description = Ihre Körperproportionen-Kal
## Home
home-no_trackers = Keine Tracker erkannt oder zugewiesen
## Status system
status_system-StatusTrackerReset = Es wird empfohlen, einen vollständigen Reset durchzuführen, da ein oder mehrere Tracker nicht kalibriert sind.
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] Derzeit nicht mit der SlimeVR-Feeder-Appverbunden.
*[other] Derzeit nicht über den SlimeVR-Treiber mit SteamVR verbunden.
}
status_system-StatusTrackerError = Der Tracker "{ $trackerName }" weist einen Fehler auf.

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 = connyecting to teh sewvew
websocket-connection_lost = oopsie woopsie~ connyection wost to teh sewvew ;m;... uwu am twying to weconnyect owo!
## Update notification
version_update-title = mew vewsion avaiwabwe: { $version }
version_update-description = cwicking "{ version_update-update }" will downwoad da SwimeVR instawlew fow u.
version_update-update = pupdate
version_update-close = cwose
## Tips
tips-find_tracker = nawt suwe whicsh twayckyaw is whicsh? shayke a twackaw and it will hyighwight the cowowesponding iytem.
tips-do_not_move_heels = ensuwe yoowr pawsies do nawt mowve duwing wecowding! ^w^
tips-file_select = dwag & dwop fiwes to use OwO, ow <u>bwowse</u>.
tips-tap_setup = u can swowly tap youw twackew 2 times to choose it insted of sewecting it fwom the menyu.
## Body parts
@@ -95,11 +100,16 @@ navbar-mounting = meownting calibwation
navbar-onboarding = suwep wisawd
navbar-settings = sewtings
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = wecowd bvh
bvh-recording = wecowding...
## Tracking pause
tracking-unpaused = pauws twacking
tracking-paused = unpauws twacking
## Widget: Overlay settings
widget-overlay = owovelay
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = mowe info
widget-imu_visualizer = wotation
widget-imu_visualizer-rotation_raw = waw
widget-imu_visualizer-rotation_preview = pwewiew
widget-imu_visualizer-rotation_hide = hoide
## Tracker status
@@ -164,6 +175,9 @@ tracker-infos-custom_name = custowm name
tracker-infos-url = twackaw uawl
tracker-infos-version = fiwmwawe vewsion
tracker-infos-hardware_rev = hawdwawe revision
tracker-infos-hardware_identifier = hawdwawe id
tracker-infos-imu = imu sensow
tracker-infos-board_type = mane bored
## Tracker settings
@@ -252,6 +266,7 @@ settings-sidebar-fk_settings = twacking settyings
settings-sidebar-gesture_control = gestauw cantwol
settings-sidebar-interface = intyawface~
settings-sidebar-osc_router = OSC wouwter
settings-sidebar-osc_trackers = VRChawt OSC Twayckaws
settings-sidebar-utils = utiwities
settings-sidebar-serial = sewiaw cownsaw
@@ -365,6 +380,7 @@ settings-general-interface-feedback_sound = feeback sownd
settings-general-interface-feedback_sound-description = dis awptshun wiww pway a sownd wen a weset is twiggered (meow~!)
settings-general-interface-feedback_sound-label = feeback sownd
settings-general-interface-feedback_sound-volume = feedback sownd volyume
settings-general-interface-theme = cowor theem
settings-general-interface-lang = sewect wanguage
settings-general-interface-lang-description = change the defawwt wanguage yuw want to use
settings-general-interface-lang-placeholder = sewect teh wanguage to use
@@ -439,7 +455,7 @@ settings-osc-vrchat-network-address-placeholder = vwchat ip addwess
settings-osc-vrchat-network-trackers = trayckawws
settings-osc-vrchat-network-trackers-description = toggle teh sending of spweciwic twackers viwa OSC
settings-osc-vrchat-network-trackers-chest = chwest~
settings-osc-vrchat-network-trackers-waist = wyayst~
settings-osc-vrchat-network-trackers-hip = hyip
settings-osc-vrchat-network-trackers-knees = knyees~
settings-osc-vrchat-network-trackers-feet = pweets~
settings-osc-vrchat-network-trackers-elbows = ewbows~
@@ -483,6 +499,12 @@ settings-osc-vmc-anchor_hip-label = anchow at hips
onboarding-skip = skipy setup
onboarding-continue = continyue
onboarding-wip = wowwk in pwowgress
onboarding-previous_step = pwevious stwep
onboarding-setup_warning =
<b>Wawning:</b> The inyitiaw setup is wequiwed fow good twacking,
it is nyeeded if this is youw fiwst time using SwimeVR.
onboarding-setup_warning-skip = skipy setup
onboarding-setup_warning-cancel = continu setup
## Wi-Fi setup
@@ -506,14 +528,29 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = gaww bawwk to meownting cawwibwation
onboarding-reset_tutorial = weset wtutowial
onboarding-reset_tutorial-description = dis featuwe isn't done, just pwess continyue
onboarding-reset_tutorial-skip = skip sedup
# Cares about multiline
onboarding-reset_tutorial-0 =
bap { $taps } times the highwighted twackew fow twiggewing yaw weset.
dis wiwl make the twackews face the same diwection as youw HMD. ^w^
# Cares about multiline
onboarding-reset_tutorial-1 =
bap { $taps } times the highwighted twackew fow twiggewing fuwl weset.
u need to be standing fow dis (i-pose). thewe is a 3 seconds deway (configuwabwe) befowe it actuawwy habbens.
this fuwly wesets duh pawsition and wotation of awl youw twackews. it shouwd fix most issue.
# Cares about multiline
onboarding-reset_tutorial-2 =
bap { $taps } time da highwighted twackew fow twiggewing meownting weset.
meownting weset hewps on how the twackews awe actuawly put on u, so if you accidentawly move dem and change how dey awe owiented by a big ameownt, this wiwl hewp.
u need to be on pose wike you awe skiing wike it's shown on da Pawtomatic Meownting wizawd and you have a 3 second deway (configuwabwe) befowe it gets twiggewed.
## Setup start
onboarding-home = wewcome to swimevr
# This cares about multilines and it's centered!!
onboarding-home-description =
bwinging fuww-bawdy twacking
to evewyone
onboarding-home-start = wets get set up!
## Enter VR part of setup
@@ -558,6 +595,27 @@ onboarding-connect_tracker-connected_trackers =
} cownyected
onboarding-connect_tracker-next = i cownyected awe my twackaws
## Tracker calibration tutorial
onboarding-calibration_tutorial = imu cawibwashun tutowiawl
onboarding-calibration_tutorial-subtitle = dis will hewp weduce twackew dwifting!!!
onboarding-calibration_tutorial-description = evewy time you tuwn on youw twackews, dey need to west fow a moment on a fwat suwface to cawibwate. wet's do da same ting by booping da "{ onboarding-calibration_tutorial-calibrate }" buddon, <b>do nyot move dem!!!</b>
onboarding-calibration_tutorial-calibrate = i pwace da twackew on da tabwe
onboarding-calibration_tutorial-status-waiting = waiiiting fur u
onboarding-calibration_tutorial-status-calibrating = cawibwating
onboarding-calibration_tutorial-status-success = congwats~!!
onboarding-calibration_tutorial-status-error = da twackew was move ;w;
## Tracker assignment tutorial
onboarding-assignment_tutorial = how to pwepawe a Swime Twackew befowe puting it on
onboarding-assignment_tutorial-first_step = 1. pwace a body pawt stickew (if you has wun) on da twackew accowding to u choosing :3
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = sticker
onboarding-assignment_tutorial-second_step = 2. put da stwap to u twackew, keep da hook an woop side of the stwap face in the fowlowing owientation:
onboarding-assignment_tutorial-second_step-continuation = da hook an woop side fow da extenson shouwd be in this owientation:
onboarding-assignment_tutorial-done = i put da stickew an stwap on :3
## Tracker assignment setup
onboarding-assign_trackers-back = go bak to wi-fi credyentials
@@ -642,6 +700,20 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] waiwst is assignyed but you nyeed unknyoun unyassignyed body pawt to awso be assignyed!
}
## Tracker mounting method choose
onboarding-choose_mounting = wut meownting cawibwation mefod to use?
# Multiline text
onboarding-choose_mounting-description = meownting owientation correct fow da pwacement of twackews on u body.
onboarding-choose_mounting-auto_mounting = awtomawic meownting
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = wecommended
onboarding-choose_mounting-auto_mounting-description = dis will automaticawwy detec da meownting diwecshuns fow aww of ya twackews fwom 2 poses
onboarding-choose_mounting-manual_mounting = manyul meownting
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = if yu know wut u r doin
onboarding-choose_mounting-manual_mounting-description = dis will let u chose da meownting diwecshun manuwawwy fow eech twackew
## Tracker manual mounting setup
onboarding-manual_mounting-back = go bak to entaw vawe
@@ -671,6 +743,24 @@ onboarding-automatic_mounting-put_trackers_on-title = put on yowo twackaws
onboarding-automatic_mounting-put_trackers_on-description = to cawibwate meownting wowations, we'we gonna use the twackaws yowo just assigned. put on awe yowo twackaws, yowo can see which awe which in the figuwe to the wowight.
onboarding-automatic_mounting-put_trackers_on-next = i haff awe my twackaws on
## Tracker proportions method choose
onboarding-choose_proportions = wut pwopowshun cawibwation mefod to use?
# Multiline string
onboarding-choose_proportions-description =
body pawpowtions awe used to know the measuwements of uw body. dey wequiwed to cawcuwate the twackews' pawsitions.
wen pawpowtions of youw body dun mach da onyes saved, youw twacking pwecision wiwl be wowse and you wiwl nyotice tings wike skating or swiding, ow youw body nyot matching youw avataw wewl.
onboarding-choose_proportions-auto_proportions = awtomatic pwopowtions
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = wecommended
onboarding-choose_proportions-auto_proportions-description = dis will guess ur pwopowshuns by wecowding a sampwe of ur movement and pass it thwough an ai
onboarding-choose_proportions-manual_proportions = manuwal pwopowtions
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = fow smol touchies
onboarding-choose_proportions-manual_proportions-description = dis will let u ajust ur pwopowtions manuwally by modifying dem diwectwy
onboarding-choose_proportions-save = sav pawpwotions
onboarding-choose_proportions-file_type = body pawpowshuns file
## Tracker manual proportions setup
onboarding-manual_proportions-back = go bawck to weset tutowiaw
@@ -732,3 +822,13 @@ onboarding-automatic_proportions-done-description = yoww body pwopowwtions cawyb
## Home
home-no_trackers = no twackaws detecyted owo wowigned
## Status system
status_system-StatusTrackerReset = it wecommended to pewfowm a fuwl weset as one or mowe twackews awe unadjussed. -w-
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] cuwwentwy nyot conect to the SwimeVR Feedew App.
*[other] cuwwentwly nawt conected to SwimeVR wiff da SwimeVR dwiver.
}
status_system-StatusTrackerError = da { $trackerName } twackew has ewwow. >~<

View File

@@ -1,4 +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!
@@ -9,10 +8,17 @@
websocket-connecting = Connecting to the server
websocket-connection_lost = Connection lost to the server. Trying to reconnect...
## Update notification
version_update-title = New version available: { $version }
version_update-description = Clicking "{ version_update-update }" will download the SlimeVR installer for you.
version_update-update = Update
version_update-close = Close
## Tips
tips-find_tracker = Not sure which tracker is which? Shake a tracker and it will highlight the corresponding item.
tips-do_not_move_heels = Ensure your heels do not move during recording!
tips-file_select = Drag & drop files to use, or <u>browse</u>.
tips-tap_setup = You can slowly tap 2 times your tracker to choose it instead of selecting it from the menu.
## Body parts
body_part-NONE = Unassigned
@@ -85,10 +91,14 @@ navbar-mounting = Mounting Calibration
navbar-onboarding = Setup Wizard
navbar-settings = Settings
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Record BVH
bvh-recording = Recording...
## Tracking pause
tracking-unpaused = Pause tracking
tracking-paused = Unpause tracking
## Widget: Overlay settings
widget-overlay = Overlay
widget-overlay-is_visible_label = Show Overlay in SteamVR
@@ -111,6 +121,7 @@ widget-developer_mode-more_info = More info
widget-imu_visualizer = Rotation
widget-imu_visualizer-rotation_raw = Raw
widget-imu_visualizer-rotation_preview = Preview
widget-imu_visualizer-rotation_hide = Hide
## Tracker status
tracker-status-none = No Status
@@ -145,6 +156,9 @@ tracker-infos-custom_name = Custom Name
tracker-infos-url = Tracker URL
tracker-infos-version = Firmware Version
tracker-infos-hardware_rev = Hardware Revision
tracker-infos-hardware_identifier = Hardware ID
tracker-infos-imu = IMU Sensor
tracker-infos-board_type = Main board
## Tracker settings
tracker-settings-back = Go back to trackers list
@@ -207,7 +221,7 @@ tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part } left contro
tracker_selection_menu-unassigned = Unassigned Trackers
tracker_selection_menu-assigned = Assigned Trackers
tracker_selection_menu-dont_assign = Do not assign
tracker_selection_menu-dont_assign = Unassign
# This line cares about multilines.
# <b>text</b> means that the text should be bold.
@@ -229,6 +243,7 @@ settings-sidebar-fk_settings = Tracking settings
settings-sidebar-gesture_control = Gesture control
settings-sidebar-interface = Interface
settings-sidebar-osc_router = OSC router
settings-sidebar-osc_trackers = VRChat OSC Trackers
settings-sidebar-utils = Utilities
settings-sidebar-serial = Serial console
@@ -391,7 +406,7 @@ settings-osc-vrchat = VRChat OSC Trackers
# This cares about multilines
settings-osc-vrchat-description =
Change VRChat-specific settings to receive HMD data and send
trackers data for FBT (works on Quest standalone).
tracker data for FBT without SteamVR (ex. Quest standalone).
settings-osc-vrchat-enable = Enable
settings-osc-vrchat-enable-description = Toggle the sending and receiving of data.
settings-osc-vrchat-enable-label = Enable
@@ -409,7 +424,7 @@ settings-osc-vrchat-network-address-placeholder = VRChat ip address
settings-osc-vrchat-network-trackers = Trackers
settings-osc-vrchat-network-trackers-description = Toggle the sending of specific trackers via OSC.
settings-osc-vrchat-network-trackers-chest = Chest
settings-osc-vrchat-network-trackers-waist = Waist
settings-osc-vrchat-network-trackers-hip = Hip
settings-osc-vrchat-network-trackers-knees = Knees
settings-osc-vrchat-network-trackers-feet = Feet
settings-osc-vrchat-network-trackers-elbows = Elbows
@@ -476,7 +491,23 @@ onboarding-wifi_creds-password =
## Mounting setup
onboarding-reset_tutorial-back = Go Back to Mounting calibration
onboarding-reset_tutorial = Reset tutorial
onboarding-reset_tutorial-description = This feature isn't done, just press continue
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-skip = Skip step
# Cares about multiline
onboarding-reset_tutorial-0 = Tap { $taps } times the highlighted tracker for triggering yaw reset.
This will make the trackers face the same direction as your HMD.
# Cares about multiline
onboarding-reset_tutorial-1 = Tap { $taps } times the highlighted tracker for triggering full reset.
You need to be standing for this (i-pose). There is a 3 seconds delay (configurable) before it actually happens.
This fully resets the position and rotation of all your trackers. It should fix most issues.
# Cares about multiline
onboarding-reset_tutorial-2 = Tap { $taps } times the highlighted tracker for triggering mounting reset.
Mounting reset helps on how the trackers are actually put on you, so if you accidentally moved them and changed how they are oriented by a big amount, this will help.
You need to be on a pose like you are skiing like it's shown on the Automatic Mounting wizard and you have a 3 second delay (configurable) before it gets triggered.
## Setup start
onboarding-home = Welcome to SlimeVR
@@ -520,6 +551,25 @@ onboarding-connect_tracker-connected_trackers = { $amount ->
} connected
onboarding-connect_tracker-next = I connected all my trackers
## Tracker calibration tutorial
onboarding-calibration_tutorial = IMU Calibration Tutorial
onboarding-calibration_tutorial-subtitle = This will help reduce tracker drifting!
onboarding-calibration_tutorial-description = Every time you turn on your trackers, they need to rest for a moment on a flat surface to calibrate. Let's do the same thing by clicking the "{ onboarding-calibration_tutorial-calibrate }" button, <b>do not move them!</b>
onboarding-calibration_tutorial-calibrate = I placed my trackers on the table
onboarding-calibration_tutorial-status-waiting = Waiting for you
onboarding-calibration_tutorial-status-calibrating = Calibrating
onboarding-calibration_tutorial-status-success = Nice!
onboarding-calibration_tutorial-status-error = The tracker was moved
## Tracker assignment tutorial
onboarding-assignment_tutorial = How to prepare a Slime Tracker before putting it on
onboarding-assignment_tutorial-first_step = 1. Place a body part sticker (if you have one) on the tracker according to your choosing
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Sticker
onboarding-assignment_tutorial-second_step = 2. Attach the strap to your tracker, keeping the hook and loop side of the strap face in the following orientation:
onboarding-assignment_tutorial-second_step-continuation = The hook and loop side for the extension should be in this orientation:
onboarding-assignment_tutorial-done = I put stickers and straps!
## Tracker assignment setup
onboarding-assign_trackers-back = Go Back to Wi-Fi Credentials
onboarding-assign_trackers-title = Assign trackers
@@ -595,13 +645,15 @@ onboarding-assign_trackers-warning-WAIST = Waist is assigned but you need { $una
## Tracker mounting method choose
onboarding-choose_mounting = What mounting calibration method to use?
# Multiline text
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 = Recommended
onboarding-choose_mounting-auto_mounting-subtitle = 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 = If you know what you are doing
onboarding-choose_mounting-manual_mounting-subtitle = Recommended
onboarding-choose_mounting-manual_mounting-description = This will let you choose the mounting direction manually for each tracker
@@ -634,6 +686,9 @@ onboarding-automatic_mounting-put_trackers_on-next = I have all my trackers on
## Tracker proportions method choose
onboarding-choose_proportions = What proportion calibration method to use?
# Multiline string
onboarding-choose_proportions-description = Body proportions are used to know the measurements of your body. They're required to calculate the trackers' positions.
When proportions of your body don't match the ones saved, your tracking precision will be worse and you will notice things like skating or sliding, or your body not matching your avatar well.
onboarding-choose_proportions-auto_proportions = Automatic proportions
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Recommended
@@ -642,6 +697,8 @@ 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-file_type = Body proportions file
## Tracker manual proportions setup
onboarding-manual_proportions-back = Go Back to Reset tutorial
@@ -700,3 +757,11 @@ onboarding-automatic_proportions-done-description = Your body proportions' calib
## Home
home-no_trackers = No trackers detected or assigned
## Status system
status_system-StatusTrackerReset = It is recommended to perform a full reset as one or more trackers are unadjusted.
status_system-StatusSteamVRDisconnected = { $type ->
*[steamvr] Currently not connected to SteamVR via the SlimeVR driver.
[steamvr_feeder] Currently not connected to the SlimeVR Feeder App.
}
status_system-StatusTrackerError = The { $trackerName } tracker has an error.

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 = Conectando al servidor
websocket-connection_lost = Conexión al servidor perdida. Intentando reconectar...
## Update notification
version_update-title = Nueva versión disponible: { $version }
version_update-description = Presionando «{ version_update-update }» descargara un instalador de SlimeVR para usar.
version_update-update = Actualizar
version_update-close = Cerrar
## Tips
tips-find_tracker = ¿No estás seguro de cuál sensor es cuál? Agita un sensor y se resaltará donde está asignado.
tips-do_not_move_heels = ¡Asegúrate de no mover los talones en la grabación!
tips-file_select = Arrastra y suelta archivos para usarlos, o <u>selecciónalos<u>.
tips-tap_setup = Puedes tocar lentamente 2 veces el tracker para seleccionarlo en lugar de seleccionarlo desde el menú.
## Body parts
@@ -95,11 +100,16 @@ navbar-mounting = Calibración de montura
navbar-onboarding = Asistente de configuración
navbar-settings = Ajustes
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Grabar BVH
bvh-recording = Grabando...
## Tracking pause
tracking-unpaused = Pausar el tracking
tracking-paused = Reanudar el tracking
## Widget: Overlay settings
widget-overlay = Overlay
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = More info
widget-imu_visualizer = Rotation
widget-imu_visualizer-rotation_raw = Raw
widget-imu_visualizer-rotation_preview = Preview
widget-imu_visualizer-rotation_hide = Ocultar
## Tracker status
@@ -164,6 +175,9 @@ tracker-infos-custom_name = Nombre personalizado
tracker-infos-url = URL del sensor
tracker-infos-version = Versión del firmware
tracker-infos-hardware_rev = Revisión del hardware
tracker-infos-hardware_identifier = ID del hardware
tracker-infos-imu = Sensor IMU
tracker-infos-board_type = Placa principal
## Tracker settings
@@ -252,6 +266,7 @@ settings-sidebar-fk_settings = Ajustes de FK
settings-sidebar-gesture_control = Control de gestos
settings-sidebar-interface = Interfaz
settings-sidebar-osc_router = Router OSC
settings-sidebar-osc_trackers = Sensores OSC de VRChat
settings-sidebar-utils = Utilidades
settings-sidebar-serial = Consola serial
@@ -310,9 +325,13 @@ settings-general-fk_settings-leg_tweak-floor_clip = Clip del suelo
# 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 = Corrección del patinaje
settings-general-fk_settings-leg_tweak-toe_snap = Encajado de dedos
settings-general-fk_settings-leg_tweak-foot_plant = Plantado del pie
settings-general-fk_settings-leg_tweak-skating_correction-amount = Agresividad de la corrección del patinaje
settings-general-fk_settings-leg_tweak-skating_correction-description = Corrección del patinaje corrige el patinaje en hielo que sucede en los pies, pero puede disminuir la precisión de ciertos patrones de movimientos. Al activar esto, asegúrate de realizar un reinicio completo y recalibrar en el juego.
settings-general-fk_settings-leg_tweak-floor_clip-description = El clip del suelo puede reducir o incluso evitar que tus pies atraviesen el suelo. Al activar esto, asegúrate de realizar un reinicio completo y recalibrar en el juego.
settings-general-fk_settings-leg_tweak-toe_snap-description = El encajado de dedos intenta adivinar la rotación de los pies si sus respectivos trackers no están en uso.
settings-general-fk_settings-leg_tweak-foot_plant-description = El plantado del pie rota los pies para que sean paralelos con el suelo al entrar en contacto.
settings-general-fk_settings-leg_fk = Tracking de piernas
settings-general-fk_settings-arm_fk = Trackeo de brazos
settings-general-fk_settings-arm_fk-description = Cambia cómo el movimiento de los brazos es detectado.
@@ -357,6 +376,11 @@ settings-general-interface-dev_mode-label = Modo desarrollador
settings-general-interface-serial_detection = Detección de dispositivo serial
settings-general-interface-serial_detection-description = Esta opción mostrará un notificación cada vez que conectes un nuevo dispositivo serial que pueda ser un sensor. Ayuda a mejorar el proceso de configuración de un sensor.
settings-general-interface-serial_detection-label = Detección de dispositivo serial
settings-general-interface-feedback_sound = Sonido de feedback
settings-general-interface-feedback_sound-description = Esta opción reproducirá un sonido cuando se realice un reinicio.
settings-general-interface-feedback_sound-label = Sonido de feedback
settings-general-interface-feedback_sound-volume = Volumen del sonido de feedback
settings-general-interface-theme = Tema de color
settings-general-interface-lang = Selecciona un idioma
settings-general-interface-lang-description = Cambia el idioma que quieras usar.
settings-general-interface-lang-placeholder = Selecciona el idioma a utilizar
@@ -431,7 +455,7 @@ settings-osc-vrchat-network-address-placeholder = Dirección IP de VRChat
settings-osc-vrchat-network-trackers = Sensores
settings-osc-vrchat-network-trackers-description = Habilita el envío de sensores específicos mediante OSC.
settings-osc-vrchat-network-trackers-chest = Pecho
settings-osc-vrchat-network-trackers-waist = Cintura
settings-osc-vrchat-network-trackers-hip = Cadera
settings-osc-vrchat-network-trackers-knees = Rodillas
settings-osc-vrchat-network-trackers-feet = Pies
settings-osc-vrchat-network-trackers-elbows = Codos
@@ -504,14 +528,29 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Volver a la calibración de montura
onboarding-reset_tutorial = Reiniciar tutorial
onboarding-reset_tutorial-description = Esta aún parte no está finalizada, por favor presione continuar
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
onboarding-home = Bienvenido a SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
¡Acercando el seguimiento
de cuerpo completo a todos!
onboarding-home-start = ¡Comencemos!
## Enter VR part of setup
@@ -556,6 +595,27 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = He conectado todos mis sensores
## Tracker calibration tutorial
onboarding-calibration_tutorial = Tutorial de calibración de IMU
onboarding-calibration_tutorial-subtitle = ¡Esto te ayudara a reducir la desviación del tracker!
onboarding-calibration_tutorial-description = Cada vez que enciendes tus trackers, van a necesitar descansar un ratito en una superficie plana para calibrarse. Tratemos de hacer lo mismo presionando el botón «{ onboarding-calibration_tutorial-calibrate }», <b>¡No los muevas!</b>
onboarding-calibration_tutorial-calibrate = Puse los sensores en una mesa.
onboarding-calibration_tutorial-status-waiting = Esperando por ti
onboarding-calibration_tutorial-status-calibrating = Calibrando
onboarding-calibration_tutorial-status-success = ¡Genial!
onboarding-calibration_tutorial-status-error = El tracker fue movido
## Tracker assignment tutorial
onboarding-assignment_tutorial = Como preparar un Tracker Slime antes de ponertelo
onboarding-assignment_tutorial-first_step = 1. Pon un sticker con la parte del cuerpo de tu elección (si tenes uno)
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Sticker
onboarding-assignment_tutorial-second_step = 2. Coloque la correa en el tracker, manteniendo el lado con velcro de la correa en la siguiente orientación:
onboarding-assignment_tutorial-second_step-continuation = El lado con velcro en las extensiones deben también estar en la siguiente orientación:
onboarding-assignment_tutorial-done = ¡Puse las correas y stickers!
## Tracker assignment setup
onboarding-assign_trackers-back = Volver a las credenciales Wi-Fi
@@ -640,6 +700,20 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] La cintura está asignada, pero necesitas asignar la parte del cuerpo desconocida sin asignar.
}
## Tracker mounting method choose
onboarding-choose_mounting = ¿Qué método de calibración de montura quiere usar?
# Multiline text
onboarding-choose_mounting-description = La orientación de montura corrige la colocación (o orientación) de los trackers en tu cuerpo.
onboarding-choose_mounting-auto_mounting = Montura automática
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Recomendado
onboarding-choose_mounting-auto_mounting-description = Esto detectará automáticamente las direcciones de montura para todos tus trackers a partir de 2 poses
onboarding-choose_mounting-manual_mounting = Montura manual
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Si sabes lo que estás haciendo
onboarding-choose_mounting-manual_mounting-description = Esto te permitirá elegir la dirección de montura manualmente para cada tracker.
## Tracker manual mounting setup
onboarding-manual_mounting-back = Volver para entrar a la RV
@@ -669,6 +743,24 @@ onboarding-automatic_mounting-put_trackers_on-title = Ponte tus sensores
onboarding-automatic_mounting-put_trackers_on-description = Para calibrar la ubicación de tus monturas, usaremos los sensores que has asignado. Ponte todos tus sensores, puedes ver cuál es cual en la figura de la derecha.
onboarding-automatic_mounting-put_trackers_on-next = Tengo puestos todos mis sensores
## Tracker proportions method choose
onboarding-choose_proportions = ¿Qué método de calibración de proporciones quiere usar?
# Multiline string
onboarding-choose_proportions-description =
Las proporciones del cuerpo se utilizan para conocer las medidas de todo tu cuerpo. Es necesario para calcular las posiciones de los trackers.
Cuando las proporciones de tu cuerpo no coinciden con las guardadas, la precisión del senseo será peor y notarás cosas como patinaje o deslizamiento, o que tu cuerpo no coincide bien con tu avatar.
onboarding-choose_proportions-auto_proportions = Proporciones automáticas
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Recomendado
onboarding-choose_proportions-auto_proportions-description = Esto adivinará tus proporciones en base de muestras de tus movimientos y pasándola a través de un algoritmo.
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-file_type = Archivo de proporciones del cuerpo
## Tracker manual proportions setup
onboarding-manual_proportions-back = Volver al tutorial de reinicio
@@ -730,3 +822,13 @@ onboarding-automatic_proportions-done-description = ¡La calibración de tus pro
## Home
home-no_trackers = No hay sensores detectados o asignados
## Status system
status_system-StatusTrackerReset = Se recomienda realizar un reinicio completo ya que uno o más trackers están sin reiniciar.
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] Actualmente no está conectado al SlimeVR Feeder
*[other] Actualmente no está conectado a SteamVR a través del driver de SlimeVR.
}
status_system-StatusTrackerError = El tracker { $trackerName } tiene un error.

View File

@@ -30,7 +30,6 @@ body_part-RIGHT_HAND = Oikea käsi
body_part-RIGHT_UPPER_LEG = Oikea reisi
body_part-RIGHT_LOWER_LEG = Oikea nilkka
body_part-RIGHT_FOOT = Oikea jalkaterä
body_part-RIGHT_CONTROLLER = Oikea ohjain
body_part-CHEST = Rinta
body_part-WAIST = Vyötärö
body_part-HIP = Lonkka
@@ -41,19 +40,20 @@ body_part-LEFT_HAND = Vasen käsi
body_part-LEFT_UPPER_LEG = Vasen reisi
body_part-LEFT_LOWER_LEG = Vasen nilkka
body_part-LEFT_FOOT = Vasen jalkaterä
body_part-LEFT_CONTROLLER = Vasen ohjain
## Proportions
skeleton_bone-NONE = Ei mikään
skeleton_bone-HEAD = Pään säätö
skeleton_bone-NECK = Kaulan pituus
skeleton_bone-torso_group = Vartalon pituus
skeleton_bone-CHEST = Rinnan pituus
skeleton_bone-CHEST_OFFSET = Rinnan keskitys
skeleton_bone-WAIST = Vyötärön pituus
skeleton_bone-HIP = Lonkan pituus
skeleton_bone-HIP_OFFSET = Lonkan keskitys
skeleton_bone-HIPS_WIDTH = Lonkan leveys
skeleton_bone-leg_group = Jalan pituus
skeleton_bone-UPPER_LEG = Yläjalan pituus
skeleton_bone-LOWER_LEG = Säären pituus
skeleton_bone-FOOT_LENGTH = Jalkaterän pituus
@@ -61,18 +61,19 @@ skeleton_bone-FOOT_SHIFT = Jalkaterän säätö
skeleton_bone-SKELETON_OFFSET = Luurangon keskitys
skeleton_bone-SHOULDERS_DISTANCE = Olkapäiden etäisyys
skeleton_bone-SHOULDERS_WIDTH = Olkapäiden leveys
skeleton_bone-arm_group = Käsivarren pituus
skeleton_bone-UPPER_ARM = Olkavarren pituus
skeleton_bone-LOWER_ARM = Kyynärvarren pituus
skeleton_bone-CONTROLLER_Y = Ohjaimen Etäisyys Y
skeleton_bone-CONTROLLER_Z = Ohjaimen Etäisyys Z
skeleton_bone-HAND_Y = Käden Etäisyys Y
skeleton_bone-HAND_Z = Käden Etäisyys Z
skeleton_bone-ELBOW_OFFSET = Kyynärpään keskitys
## Tracker reset buttons
reset-reset_all = Nollaa kaikki mittasuhteet
reset-full = Nollaa
reset-full = Täysinollaus
reset-mounting = Nollaa Asennus
reset-quick = Pikanollaus
reset-yaw = Nollaa Kallistuma
## Serial detection stuff
@@ -160,6 +161,8 @@ tracker-infos-manufacturer = Valmistaja
tracker-infos-display_name = Näyttönimi
tracker-infos-custom_name = Mukautettu Nimi
tracker-infos-url = Jäljittimen URL
tracker-infos-version = Laiteohjelmiston Versio
tracker-infos-hardware_rev = Laitteston Tarkistus
## Tracker settings
@@ -276,8 +279,6 @@ settings-general-tracker_mechanics-drift_compensation-max_resets-label = Käytä
## FK/Tracking settings
settings-general-fk_settings = Jäljityksen asetukset
settings-general-fk_settings-leg_tweak = Jalkojen säätöjä
settings-general-fk_settings-leg_tweak-description = Floor-clip voi vähentää tai jopa täysin estää jalan läpikulkua lattiasta, mutta voi aiheuttaa ongelmia kun olet polvillasi. Skating-correction ehkäisee luistelumaista liikettä, mutta voi heikentää tiettyjen liikekuvioiden tarkkuutta.
# 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
@@ -287,7 +288,14 @@ settings-general-fk_settings-leg_tweak-floor_clip = Floor clip
# 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 = Skating correction
settings-general-fk_settings-leg_tweak-toe_snap = Toe snap
settings-general-fk_settings-leg_tweak-foot_plant = Foot plant
settings-general-fk_settings-leg_tweak-skating_correction-amount = Skating correction vahvuus
settings-general-fk_settings-leg_tweak-skating_correction-description = Skating correction helpottaa jalkojen luistelua, mutta voi heikentää tarkkuutta tietyissä liikekuvioissa. Kun otat käyttöön, muista tehdä täysi nollaus ja kalibroida uudelleen pelissä.
settings-general-fk_settings-leg_tweak-floor_clip-description = Floor clip voi vähentää tai korjata jalan kulun lattian läpi. Kun otat käyttöön, muista tehdä täysi nollaus ja kalibroida uudelleen pelissä.
settings-general-fk_settings-leg_tweak-toe_snap-description = Toe snap yrittää arvata varpaiden asennon jos jalkaterän jäljitintä ei ole käytössä.
settings-general-fk_settings-leg_tweak-foot_plant-description = Foot plant asettaa jalkateräsi yhdensuuntaisesti maan kanssa kosketuksessa.
settings-general-fk_settings-leg_fk = Jalkojen jäljitys
settings-general-fk_settings-arm_fk = Käsivarsien jäljitys
settings-general-fk_settings-arm_fk-description = Muuta tapaa, jolla käsivarsia jäljitetään.
settings-general-fk_settings-arm_fk-force_arms = Pakota kädet HMD:ltä
@@ -312,12 +320,12 @@ settings-general-gesture_control-taps =
[one] 1 napautus
*[other] { $amount } napautusta
}
settings-general-gesture_control-quickResetEnabled = Ota käyttöön pikanollaus napautus
settings-general-gesture_control-quickResetDelay = Pikanollaus viive
settings-general-gesture_control-quickResetTaps = Napautuksia pikanollaukseen
settings-general-gesture_control-resetEnabled = Ota käyttöön nollaus napautus
settings-general-gesture_control-resetDelay = Nollaus viive
settings-general-gesture_control-resetTaps = Napautuksia nollaukseen
settings-general-gesture_control-yawResetEnabled = Ota käyttöön kallistumanollaus napautus
settings-general-gesture_control-yawResetDelay = Kallistumanollaus viive
settings-general-gesture_control-yawResetTaps = Napautuksia kallistumanollaukseen.
settings-general-gesture_control-fullResetEnabled = Ota käyttöön täysinollaus napautus
settings-general-gesture_control-fullResetDelay = Täysinollaus viive
settings-general-gesture_control-fullResetTaps = Napautuksia täysinollaukseen
settings-general-gesture_control-mountingResetEnabled = Ota käyttöön asennusnollaus napautus
settings-general-gesture_control-mountingResetDelay = Asennusnollaus viive
settings-general-gesture_control-mountingResetTaps = Napautuksia asennusnollaukseen
@@ -331,6 +339,11 @@ settings-general-interface-dev_mode-label = Kehittäjätila
settings-general-interface-serial_detection = Sarjalaitteen tunnistus
settings-general-interface-serial_detection-description = Tämä vaihtoehto näyttää ponnahdusikkunan aina, kun liität uuden sarjalaitteen, joka voi olla jäljitin. Se auttaa parantamaan jäljittimen asennusprosessia.
settings-general-interface-serial_detection-label = Sarjalaitteen tunnistus
settings-general-interface-feedback_sound = Palaute ääni
settings-general-interface-feedback_sound-description = Tämä asetus toistaa äänen nollauksen tapahtuessa.
settings-general-interface-feedback_sound-label = Palaute ääni
settings-general-interface-feedback_sound-volume = Palaute äänen voimakkuus
settings-general-interface-theme = Väri teema
settings-general-interface-lang = Valitse kieli
settings-general-interface-lang-description = Vaihda oletuskieli, jota haluat käyttää.
settings-general-interface-lang-placeholder = Valitse käytettävä kieli
@@ -405,11 +418,41 @@ settings-osc-vrchat-network-address-placeholder = VRChat IP-osoite
settings-osc-vrchat-network-trackers = Jäljittimet
settings-osc-vrchat-network-trackers-description = Vaihda tiettyjen jäljittimien lähettäminen OSC:n kautta.
settings-osc-vrchat-network-trackers-chest = Rinta
settings-osc-vrchat-network-trackers-waist = Vyötärö
settings-osc-vrchat-network-trackers-knees = Polvet
settings-osc-vrchat-network-trackers-feet = Jalat
settings-osc-vrchat-network-trackers-elbows = Kyynärpäät
## VMC OSC settings
settings-osc-vmc = Virtual Motion Capture
# This cares about multilines
settings-osc-vmc-description =
Muuta VMC (Virtual Motion Capture) -protokollan asetuksia
lähettääksesi ja vastaanottaaksesi SlimeVR:n luutietoja muihin sovelluksiin.
settings-osc-vmc-enable = Käytä
settings-osc-vmc-enable-description = Vaihda tietojen lähettäminen ja vastaanottaminen.
settings-osc-vmc-enable-label = Käytä
settings-osc-vmc-network = Verkkoportit
settings-osc-vmc-network-description = Aseta portit tietojen kuunteluun ja lähettämiseen VMC:n kautta
settings-osc-vmc-network-port_in =
.label = Portti sisään
.placeholder = Portti sisään (oletus: 39540)
settings-osc-vmc-network-port_out =
.label = Portti ulos
.placeholder = Portti ulos (oletus: 39539)
settings-osc-vmc-network-address = Verkon osoite
settings-osc-vmc-network-address-description = Määritä osoite, johon tietoja lähetetään VMC:n kautta
settings-osc-vmc-network-address-placeholder = IPV4-osoite
settings-osc-vmc-vrm = VRM-malli
settings-osc-vmc-vrm-description = Lataa VRM-malli salliaksesi pääankkurin ja mahdollistaaksesi paremman yhteensopivuuden muiden sovellusten kanssa
settings-osc-vmc-vrm-model_unloaded = Mallia ei ole ladattu
settings-osc-vmc-vrm-model_loaded =
{ $titled ->
[true] Malli ladattu: { $name }
*[other] Nimetön malli ladattu
}
settings-osc-vmc-anchor_hip = Ankkuri lantiolla
## Setup/onboarding menu
onboarding-skip = Ohita asennus
@@ -442,10 +485,6 @@ onboarding-reset_tutorial-description = Tämä ominaisuus ei ole valmis, paina v
## Setup start
onboarding-home = Tervetuloa SlimeVR:ään
# This cares about multilines and it's centered!!
onboarding-home-description =
Tuomme kaikille
täysikehojäljityksen
onboarding-home-start = Mennään asentamaan!
## Enter VR part of setup
@@ -471,12 +510,21 @@ onboarding-connect_tracker-description-p1 = Yhdistä vain kaikki, joita ei ole v
## 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

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 = Connexion au serveur
websocket-connection_lost = Connexion avec le serveur perdue. Reconnexion...
## Update notification
version_update-title = Nouvelle version disponible: { $version }
version_update-description = Cliquer sur « { version_update-update } » téléchargera l'installateur SlimeVR pour vous.
version_update-update = Mettre à jour
version_update-close = Fermer
## Tips
tips-find_tracker = Impossible de différencier vos capteurs? Secouez-en un pour qu'il soit mis en évidence.
tips-do_not_move_heels = Assurez-vous de ne pas bouger vos pieds pendant la calibration!
tips-find_tracker = Impossible de différencier vos capteurs ? Secouez-en un pour qu'il soit mis en évidence.
tips-do_not_move_heels = Assurez-vous de ne pas bouger vos pieds pendant la calibration !
tips-file_select = Glissez et déposez des fichiers à utiliser, ou <u>parcourir</u>.
tips-tap_setup = Vous pouvez tapoter lentement votre capteur 2 fois pour le choisir au lieu de le sélectionner depuis le menu.
## Body parts
@@ -49,17 +54,17 @@ skeleton_bone-HEAD = Décalage de la tête
skeleton_bone-NECK = Longueur du cou
skeleton_bone-torso_group = Longueur du torse
skeleton_bone-CHEST = Longueur de la poitrine
skeleton_bone-CHEST_OFFSET = Écart de la poitrine
skeleton_bone-CHEST_OFFSET = Décalage de la poitrine
skeleton_bone-WAIST = Longueur de la taille
skeleton_bone-HIP = Longueur des hanches
skeleton_bone-HIP_OFFSET = Écart de la hanche
skeleton_bone-HIP_OFFSET = Décalage de la hanche
skeleton_bone-HIPS_WIDTH = Largeur des hanches
skeleton_bone-leg_group = Longueur des jambes
skeleton_bone-UPPER_LEG = Longueur des jambes supérieures
skeleton_bone-LOWER_LEG = Longueur des jambes inférieures
skeleton_bone-FOOT_LENGTH = Longueur des pieds
skeleton_bone-FOOT_SHIFT = Décalage des pieds
skeleton_bone-SKELETON_OFFSET = Écart du squelette
skeleton_bone-SKELETON_OFFSET = Décalage du squelette
skeleton_bone-SHOULDERS_DISTANCE = Distance des épaules
skeleton_bone-SHOULDERS_WIDTH = Largeur des épaules
skeleton_bone-arm_group = Longueur des bras
@@ -67,7 +72,7 @@ skeleton_bone-UPPER_ARM = Longueur des bras supérieurs
skeleton_bone-LOWER_ARM = Longueur des avant-bras
skeleton_bone-HAND_Y = Distance Y des mains
skeleton_bone-HAND_Z = Distance Z des mains
skeleton_bone-ELBOW_OFFSET = Écart des coudes
skeleton_bone-ELBOW_OFFSET = Décalage des coudes
## Tracker reset buttons
@@ -78,12 +83,12 @@ reset-yaw = Réinitialisation horizontale
## Serial detection stuff
serial_detection-new_device-p0 = Nouveau périphérique détecté!
serial_detection-new_device-p1 = Entrez vos identifiants Wi-Fi!
serial_detection-new_device-p0 = Nouveau périphérique détecté !
serial_detection-new_device-p1 = Entrez vos identifiants Wi-Fi !
serial_detection-new_device-p2 = Veuillez sélectionner quoi en faire
serial_detection-open_wifi = Connecter au Wi-Fi
serial_detection-open_serial = Ouvrir la console série
serial_detection-submit = Soumettre!
serial_detection-submit = Soumettre !
serial_detection-close = Fermer
## Navigation bar
@@ -95,11 +100,16 @@ navbar-mounting = Alignement des capteurs
navbar-onboarding = Assistant de configuration
navbar-settings = Réglages
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Enregistrer BVH
bvh-recording = Enregistrement...
## Tracking pause
tracking-unpaused = Pause de la capture
tracking-paused = Arrêter la pause de la capture
## Widget: Overlay settings
widget-overlay = Squelette
@@ -108,7 +118,7 @@ widget-overlay-is_mirrored_label = Afficher le squelette en tant que miroir
## Widget: Drift compensation
widget-drift_compensation-clear = Remise à zéro de la compensation de la dérive
widget-drift_compensation-clear = Réinitialiser la compensation de la dérive
## Widget: Developer settings
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = Plus d'informations
widget-imu_visualizer = Rotation
widget-imu_visualizer-rotation_raw = Brute
widget-imu_visualizer-rotation_preview = Aperçu
widget-imu_visualizer-rotation_hide = Masquer
## Tracker status
@@ -164,19 +175,22 @@ tracker-infos-custom_name = Nom personnalisé
tracker-infos-url = URL du capteur
tracker-infos-version = Version du firmware
tracker-infos-hardware_rev = Révision du hardware
tracker-infos-hardware_identifier = ID Matériel
tracker-infos-imu = Capteur IMU
tracker-infos-board_type = Carte principale
## Tracker settings
tracker-settings-back = Retour à la liste des capteurs
tracker-settings-title = Paramètres du capteur
tracker-settings-assignment_section = Attribution du capteur
tracker-settings-assignment_section-description = À quelle partie du corps le capteur est attribué.
tracker-settings-assignment_section-edit = Ré-attribuer
tracker-settings-assignment_section-description = Partie du corps à laquelle le capteur est attribué.
tracker-settings-assignment_section-edit = Changer
tracker-settings-mounting_section = Orientation du capteur
tracker-settings-mounting_section-description = Dans quelle direction pointe le capteur?
tracker-settings-mounting_section-description = Dans quelle direction pointe le capteur ?
tracker-settings-mounting_section-edit = Changer l'orientation
tracker-settings-drift_compensation_section = Permettre la compensation de la dérive
tracker-settings-drift_compensation_section-description = Ce capteur devrait-il compenser pour sa dérive si l'option est activée?
tracker-settings-drift_compensation_section-description = Ce capteur devrait-il compenser pour sa dérive quand l'option est activée ?
tracker-settings-drift_compensation_section-edit = Permettre la compensation de la dérive
# 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.
@@ -191,7 +205,7 @@ tracker-part_card-unassigned = Non-attribué
## Body assignment menu
body_assignment_menu = Où attribuer ce capteur?
body_assignment_menu = Où attribuer ce capteur ?
body_assignment_menu-description = Choisissez où attribuer ce capteur. Vous pouvez également gérer tous les capteurs à la fois au lieu d'un à la fois.
body_assignment_menu-show_advanced_locations = Afficher les emplacements d'attribution avancés
body_assignment_menu-manage_trackers = Gérer tous les capteurs
@@ -205,28 +219,28 @@ body_assignment_menu-unassign_tracker = Désattribuer
# We are using it here because english doesn't require changing the text in each case but
# maybe your language does.
-tracker_selection-part = Quel capteur à attribuer à votre
tracker_selection_menu-NONE = Quel capteur voulez-vous désattribuer?
tracker_selection_menu-HEAD = { -tracker_selection-part } tête?
tracker_selection_menu-NECK = { -tracker_selection-part } cou?
tracker_selection_menu-RIGHT_SHOULDER = { -tracker_selection-part } épaule droite?
tracker_selection_menu-RIGHT_UPPER_ARM = { -tracker_selection-part } bras droit?
tracker_selection_menu-RIGHT_LOWER_ARM = { -tracker_selection-part } avant-bras droit?
tracker_selection_menu-RIGHT_HAND = { -tracker_selection-part } main droite?
tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } cuisse droite?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } cheville droite?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } pied droit?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } manette droite?
tracker_selection_menu-CHEST = { -tracker_selection-part } poitrine?
tracker_selection_menu-WAIST = { -tracker_selection-part } taille?
tracker_selection_menu-HIP = { -tracker_selection-part } hanche?
tracker_selection_menu-LEFT_SHOULDER = { -tracker_selection-part } épaule gauche?
tracker_selection_menu-LEFT_UPPER_ARM = { -tracker_selection-part } bras gauche?
tracker_selection_menu-LEFT_LOWER_ARM = { -tracker_selection-part } avant-bras gauche?
tracker_selection_menu-LEFT_HAND = { -tracker_selection-part } main gauche?
tracker_selection_menu-LEFT_UPPER_LEG = { -tracker_selection-part } cuisse gauche?
tracker_selection_menu-LEFT_LOWER_LEG = { -tracker_selection-part } cheville gauche?
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } pied gauche?
tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part } manette gauche?
tracker_selection_menu-NONE = Quel capteur voulez-vous désattribuer ?
tracker_selection_menu-HEAD = { -tracker_selection-part } tête ?
tracker_selection_menu-NECK = { -tracker_selection-part } cou ?
tracker_selection_menu-RIGHT_SHOULDER = { -tracker_selection-part } épaule droite ?
tracker_selection_menu-RIGHT_UPPER_ARM = { -tracker_selection-part } bras droit ?
tracker_selection_menu-RIGHT_LOWER_ARM = { -tracker_selection-part } avant-bras droit ?
tracker_selection_menu-RIGHT_HAND = { -tracker_selection-part } main droite ?
tracker_selection_menu-RIGHT_UPPER_LEG = { -tracker_selection-part } cuisse droite ?
tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } cheville droite ?
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } pied droit ?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } manette droite ?
tracker_selection_menu-CHEST = { -tracker_selection-part } poitrine ?
tracker_selection_menu-WAIST = { -tracker_selection-part } taille ?
tracker_selection_menu-HIP = { -tracker_selection-part } hanche ?
tracker_selection_menu-LEFT_SHOULDER = { -tracker_selection-part } épaule gauche ?
tracker_selection_menu-LEFT_UPPER_ARM = { -tracker_selection-part } bras gauche ?
tracker_selection_menu-LEFT_LOWER_ARM = { -tracker_selection-part } avant-bras gauche ?
tracker_selection_menu-LEFT_HAND = { -tracker_selection-part } main gauche ?
tracker_selection_menu-LEFT_UPPER_LEG = { -tracker_selection-part } cuisse gauche ?
tracker_selection_menu-LEFT_LOWER_LEG = { -tracker_selection-part } cheville gauche ?
tracker_selection_menu-LEFT_FOOT = { -tracker_selection-part } pied gauche ?
tracker_selection_menu-LEFT_CONTROLLER = { -tracker_selection-part } manette gauche ?
tracker_selection_menu-unassigned = Capteurs non-attribués
tracker_selection_menu-assigned = Capteurs attribués
tracker_selection_menu-dont_assign = Ne pas attribuer
@@ -234,13 +248,13 @@ tracker_selection_menu-dont_assign = Ne pas attribuer
# <b>text</b> means that the text should be bold.
tracker_selection_menu-neck_warning =
<b>Attention:</b> Un capteur au cou peut être mortel s'il est trop serré,
la sangle pourrait couper la circulation à la tête!
la sangle pourrait couper la circulation à la tête !
tracker_selection_menu-neck_warning-done = Je suis conscient des risques
tracker_selection_menu-neck_warning-cancel = Annuler
## Mounting menu
mounting_selection_menu = Dans quelle direction pointe ce capteur?
mounting_selection_menu = Dans quelle direction pointe ce capteur ?
mounting_selection_menu-close = Fermer
## Sidebar settings
@@ -252,6 +266,7 @@ settings-sidebar-fk_settings = Paramètres de la capture
settings-sidebar-gesture_control = Contrôle gestuel
settings-sidebar-interface = Interface
settings-sidebar-osc_router = Routeur OSC
settings-sidebar-osc_trackers = Capteurs OSC VRChat
settings-sidebar-utils = Utilitaires
settings-sidebar-serial = Console série
@@ -342,15 +357,15 @@ settings-general-gesture_control-taps =
[one] 1 tap
*[other] { $amount } taps
}
settings-general-gesture_control-yawResetEnabled = Taper pour réinitialisation horizontale
settings-general-gesture_control-yawResetEnabled = Tapoter pour réinitialisation horizontale
settings-general-gesture_control-yawResetDelay = Délai de réinitialisation horizontale
settings-general-gesture_control-yawResetTaps = Tapes pour réinitialisation horizontale
settings-general-gesture_control-fullResetEnabled = Taper pour réinitialisation complète
settings-general-gesture_control-yawResetTaps = Nombre de tapes pour réinitialisation horizontale
settings-general-gesture_control-fullResetEnabled = Tapoter pour réinitialisation complète
settings-general-gesture_control-fullResetDelay = Délai de réinitialisation complète
settings-general-gesture_control-fullResetTaps = Tapes pour réinitialisation complète
settings-general-gesture_control-mountingResetEnabled = Taper pour réinitialisation de l'alignement
settings-general-gesture_control-fullResetTaps = Nombre de tapes pour réinitialisation complète
settings-general-gesture_control-mountingResetEnabled = Tapoter pour réinitialisation de l'alignement
settings-general-gesture_control-mountingResetDelay = Délai de réinitialisation de l'alignement
settings-general-gesture_control-mountingResetTaps = Tapes pour la réinitialisation de l'alignement
settings-general-gesture_control-mountingResetTaps = Nombre de tapes pour la réinitialisation de l'alignement
## Interface settings
@@ -365,9 +380,10 @@ settings-general-interface-feedback_sound = Son de retour
settings-general-interface-feedback_sound-description = Cette option va jouer un son lorsqu'une réanitilisation est enclenchée
settings-general-interface-feedback_sound-label = Son de retour
settings-general-interface-feedback_sound-volume = Volume du son de retour
settings-general-interface-lang = Sélectionner la langue
settings-general-interface-theme = Thème
settings-general-interface-lang = Langue
settings-general-interface-lang-description = Choisir la langue par défaut.
settings-general-interface-lang-placeholder = Choisissez la langue
settings-general-interface-lang-placeholder = Langue
## Serial settings
@@ -383,7 +399,7 @@ settings-serial-factory_reset = Remise à zéro
# <b>text</b> means that the text should be bold
settings-serial-factory_reset-warning =
<b>Attention:</b> Cela réinitialisera les paramètres du capteur à zéro.
Ce qui signifie que les paramètres de Wi-Fi et de calibration <b>seront tous perdus!</b>
Ce qui signifie que les paramètres de Wi-Fi et de calibration <b>seront tous perdus !</b>
settings-serial-factory_reset-warning-ok = Je sais ce que je fais
settings-serial-factory_reset-warning-cancel = Annuler
settings-serial-get_infos = Obtenir des informations
@@ -417,7 +433,7 @@ settings-osc-router-network-address-placeholder = Adresse IPv4
## OSC VRChat settings
settings-osc-vrchat = VRChat OSC Trackers
settings-osc-vrchat = Capteurs OSC VRChat
# This cares about multilines
settings-osc-vrchat-description =
Modifiez les paramètres spécifiques à VRChat pour recevoir et envoyer
@@ -439,7 +455,7 @@ settings-osc-vrchat-network-address-placeholder = Adresse IP VRChat
settings-osc-vrchat-network-trackers = capteurs
settings-osc-vrchat-network-trackers-description = Sélectionner quels capteurs envoyer via OSC.
settings-osc-vrchat-network-trackers-chest = Poitrine
settings-osc-vrchat-network-trackers-waist = Taille
settings-osc-vrchat-network-trackers-hip = Hanche
settings-osc-vrchat-network-trackers-knees = Genoux
settings-osc-vrchat-network-trackers-feet = Pieds
settings-osc-vrchat-network-trackers-elbows = Coudes
@@ -498,7 +514,7 @@ onboarding-wifi_creds = Saisir les identifiants Wi-Fi
onboarding-wifi_creds-description =
Les capteurs utiliseront ces informations d'identification pour se connecter au réseau.
Veuillez utiliser les identifiants avec lesquels vous êtes actuellement connecté.
onboarding-wifi_creds-skip = Passer la configuration Wi-Fi
onboarding-wifi_creds-skip = Passer configuration Wi-Fi
onboarding-wifi_creds-submit = Valider
onboarding-wifi_creds-ssid =
.label = Nom du Wi-Fi
@@ -512,26 +528,41 @@ 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-skip = Sauter l'étape
# Cares about multiline
onboarding-reset_tutorial-0 =
Tapotez { $taps } fois sur le capteur en surbrillance pour effectuer une réinitialisation horizontale.
Cela orientera les capteurs dans la même direction que votre casque VR.
# Cares about multiline
onboarding-reset_tutorial-1 =
Tapotez { $taps } fois sur le capteur en surbrillance pour effectuer une réinitialisation complète.
Vous devrez restez en position « i » (droit debout, bras le long du corps). Vous aurez un délai de 3 secondes (configurable) avant la réinitialisation.
Cela réinitialise complètement la position et la rotation de tout vos capteurs, ce qui devrait corriger la plupart des problèmes.
# Cares about multiline
onboarding-reset_tutorial-2 =
Tapotez { $taps } fois sur le capteur en surbrillance pour réinitialiser l'alignement des capteurs.
La réinitialisation de l'alignement des capteurs aide à définir la façon dont ces derniers sont portés sur vous. Cela aidera si vous en avez déplacé un sur vous accidentellement.
Accroupissez-vous dans une position de « ski » comme affiché sur l'assistant d'alignement des capteurs. Vous aurez un délai de 3 secondes (configurable) avant la réinitialisation.
## Setup start
onboarding-home = Bienvenue sur SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
Rendre la capture des mouvements
accessible à toutes et tous!
onboarding-home-start = Commencer!
onboarding-home-start = Commencer
## Enter VR part of setup
onboarding-enter_vr-back = Revenir à l'attribution des capteurs
onboarding-enter_vr-title = Il est temps d'entrer en réalité virtuelle!
onboarding-enter_vr-description = Enfilez tous vos capteurs puis entrez en réalité virtuelle!
onboarding-enter_vr-ready = je suis prêt!
onboarding-enter_vr-title = Allons en réalité virtuelle !
onboarding-enter_vr-description = Enfilez tous vos capteurs puis allez en réalité virtuelle !
onboarding-enter_vr-ready = Je suis prêt
## Setup done
onboarding-done-title = Vous êtes prêt!
onboarding-done-title = Vous êtes prêt !
onboarding-done-description = Amusez-vous bien :)
onboarding-done-close = Fermer le guide
@@ -539,9 +570,9 @@ onboarding-done-close = Fermer le guide
onboarding-connect_tracker-back = Revenir aux informations d'identification Wi-Fi
onboarding-connect_tracker-title = Connecter les capteurs
onboarding-connect_tracker-description-p0 = Passons maintenant à la partie amusante, en connectant tous les capteurs!
onboarding-connect_tracker-description-p0 = Passons maintenant à la partie amusante: connecter tous les capteurs !
onboarding-connect_tracker-description-p1 = Connectez chaque capteur qui n'est pas encore connecté via un port USB.
onboarding-connect_tracker-issue-serial = J'ai du mal à me connecter!
onboarding-connect_tracker-issue-serial = J'ai des problèmes de connexion !
onboarding-connect_tracker-usb = Capteur USB
onboarding-connect_tracker-connection_status-none = Recherche de capteurs
onboarding-connect_tracker-connection_status-serial_init = Connexion au périphérique en série
@@ -564,6 +595,27 @@ onboarding-connect_tracker-connected_trackers =
} connected
onboarding-connect_tracker-next = J'ai connecté tous mes capteurs
## Tracker calibration tutorial
onboarding-calibration_tutorial = Tutoriel de calibration IMU
onboarding-calibration_tutorial-subtitle = Ceci vous aidera à réduire la dérive du capteur !
onboarding-calibration_tutorial-description = Chaque fois que vous allumez vos capteurs, ils doivent rester sur une surface plane pour se calibrer. Faisons de même en cliquant sur le bouton « { onboarding-calibration_tutorial-calibrate } ». <b>Ne les déplacez pas !</b>
onboarding-calibration_tutorial-calibrate = J'ai posé mes capteurs sur la table
onboarding-calibration_tutorial-status-waiting = En attente de vous
onboarding-calibration_tutorial-status-calibrating = Calibration...
onboarding-calibration_tutorial-status-success = Génial !
onboarding-calibration_tutorial-status-error = Le capteur a été déplacé
## Tracker assignment tutorial
onboarding-assignment_tutorial = Comment préparer un capteur Slime avant de le porter
onboarding-assignment_tutorial-first_step = 1. Placez un autocollant de partie du corps (si vous en avez un) sur le capteur selon votre choix
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Autocollant
onboarding-assignment_tutorial-second_step = 2. Attachez la sangle à votre capteur en gardant le côté velcro de la sangle dans lorientation suivante:
onboarding-assignment_tutorial-second_step-continuation = La partie velcro pour lextension doit être dans cette orientation:
onboarding-assignment_tutorial-done = J'ai mis les autocollants et les sangles !
## Tracker assignment setup
onboarding-assign_trackers-back = Revenir aux identifiants Wi-Fi
@@ -586,68 +638,82 @@ onboarding-assign_trackers-next = J'ai attribué tous mes capteurs
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_FOOT =
{ $unassigned ->
[0] Le pied gauche est attribué mais il faut que la cheville gauche, la cuisse gauche et soit la poitrine, la hanche ou la taille soient également attribuées!
[1] Le pied gauche est attribué mais il faut que la cuisse gauche et soit la poitrine, la hanche ou la taille soient également attribuées!
[2] Le pied gauche est attribué mais il faut que la cheville gauche et soit la poitrine, la hanche ou la taille soient également attribuées!
[3] Le pied gauche est attribué mais il faut que la poitrine, la hanche ou la taille soient également attribuées!
[4] Le pied gauche est attribué mais il faut que la cheville gauche et la cuisse gauche soient également attribuées!
[5] Le pied gauche est attribué mais il faut que la cuisse gauche le soit également!
[6] Le pied gauche est attribué mais il faut que la cheville gauche le soit également!
*[unknown] Le pied gauche est attribué mais il faut qu'une autre partie du corps inconnue non assignée soit également attribuée!
[0] Le pied gauche est attribué mais il faut que la cheville gauche, la cuisse gauche et soit la poitrine, la hanche ou la taille soient également attribuées !
[1] Le pied gauche est attribué mais il faut que la cuisse gauche et soit la poitrine, la hanche ou la taille soient également attribuées !
[2] Le pied gauche est attribué mais il faut que la cheville gauche et soit la poitrine, la hanche ou la taille soient également attribuées !
[3] Le pied gauche est attribué mais il faut que la poitrine, la hanche ou la taille soient également attribuées !
[4] Le pied gauche est attribué mais il faut que la cheville gauche et la cuisse gauche soient également attribuées !
[5] Le pied gauche est attribué mais il faut que la cuisse gauche le soit également !
[6] Le pied gauche est attribué mais il faut que la cheville gauche le soit également !
*[unknown] Le pied gauche est attribué mais il faut qu'une autre partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_FOOT =
{ $unassigned ->
[0] Le pied droit est attribué mais il faut que la cheville droite, la cuisse droite et soit la poitrine, la hanche ou la taille soient également attribuées!
[1] Le pied droit est assigné mais il faut que la cuisse droite et soit la poitrine, la hanche ou la taille soient également attribuées!
[2] Le pied droit est assigné mais il faut que la cheville droite et soit la poitrine, la hanche ou la taille soient également attribuées!
[3] Le pied droit est attribué mais il faut que la poitrine, la hanche ou la taille soient également attribuées!
[4] Le pied droit est attribué mais il faut que la cheville droite et la cuisse droite soient également attribuées!
[5] Le pied droit est attribué mais il faut que la cuisse droite le soit également!
[6] Le pied droit est attribué mais il faut que la cheville droite le soit également!
*[unknown] Le pied droit est assigné mais il faut qu'une autre partie du corps inconnue non assignée soit également attribuée!
[0] Le pied droit est attribué mais il faut que la cheville droite, la cuisse droite et soit la poitrine, la hanche ou la taille soient également attribuées !
[1] Le pied droit est assigné mais il faut que la cuisse droite et soit la poitrine, la hanche ou la taille soient également attribuées !
[2] Le pied droit est assigné mais il faut que la cheville droite et soit la poitrine, la hanche ou la taille soient également attribuées !
[3] Le pied droit est attribué mais il faut que la poitrine, la hanche ou la taille soient également attribuées !
[4] Le pied droit est attribué mais il faut que la cheville droite et la cuisse droite soient également attribuées !
[5] Le pied droit est attribué mais il faut que la cuisse droite le soit également !
[6] Le pied droit est attribué mais il faut que la cheville droite le soit également !
*[unknown] Le pied droit est assigné mais il faut qu'une autre partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_LOWER_LEG =
{ $unassigned ->
[0] La cheville gauche est attribuée mais il faut que la cuisse gauche et soit la poitrine, la hanche ou la taille soient également attribuées!
[1] La cheville gauche est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées!
[2] La cheville gauche est attribuée mais il faut que la cuisse gauche soit également attribuée!
*[unknown] La cheville gauche est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée!
[0] La cheville gauche est attribuée mais il faut que la cuisse gauche et soit la poitrine, la hanche ou la taille soient également attribuées !
[1] La cheville gauche est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées !
[2] La cheville gauche est attribuée mais il faut que la cuisse gauche soit également attribuée !
*[unknown] La cheville gauche est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_LOWER_LEG =
{ $unassigned ->
[0] La cheville droite est attribuée mais il faut que la cuisse droite et soit la poitrine, la hanche ou la taille soient également attribuées!
[1] La cheville droite est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées!
[0] La cheville droite est attribuée mais il faut que la cuisse droite et soit la poitrine, la hanche ou la taille soient également attribuées !
[1] La cheville droite est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées !
[2] La cheville droite est attribuée mais il faut que la cuisse droite soit également attribuée !
*[unknown] La cheville droite est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée!
*[unknown] La cheville droite est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_UPPER_LEG =
{ $unassigned ->
[0] La cuisse gauche est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées!
*[unknown] La cuisse gauche est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée!
[0] La cuisse gauche est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées !
*[unknown] La cuisse gauche est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_UPPER_LEG =
{ $unassigned ->
[0] La cuisse droite est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées!
*[unknown] La cuisse droite est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée!
[0] La cuisse droite est attribuée mais il faut que la poitrine, la hanche ou la taille soient également attribuées !
*[unknown] La cuisse droite est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-HIP =
{ $unassigned ->
[0] La hanche est attribuée mais il faut que la poitrine le soit aussi!
*[unknown] La hanche est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée!
[0] La hanche est attribuée mais il faut que la poitrine le soit aussi !
*[unknown] La hanche est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée !
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-WAIST =
{ $unassigned ->
[0] La taille est attribuée mais il faut que la poitrine le soit aussi!
*[unknown] La taille est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée!
[0] La taille est attribuée mais il faut que la poitrine le soit aussi !
*[unknown] La taille est attribuée mais il faut qu'une partie du corps inconnue non assignée soit également attribuée !
}
## Tracker mounting method choose
onboarding-choose_mounting = Quelle méthode de calibration de lalignement utiliser ?
# Multiline text
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-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-description = Ceci vous permettra de choisir la direction de chaque capteur manuellement
## Tracker manual mounting setup
onboarding-manual_mounting-back = Retournez à entrer dans la réalité virtuelle
@@ -664,8 +730,8 @@ onboarding-automatic_mounting-description = Pour que vos capteurs SlimeVR foncti
onboarding-automatic_mounting-manual_mounting = Alignement manuel
onboarding-automatic_mounting-next = Prochaine étape
onboarding-automatic_mounting-prev_step = Étape précédente
onboarding-automatic_mounting-done-title = C'est terminé!
onboarding-automatic_mounting-done-description = L'alignement des capteurs est calibré!
onboarding-automatic_mounting-done-title = Alignements calibrés.
onboarding-automatic_mounting-done-description = La calibration de l'alignement de vos capteurs est terminée !
onboarding-automatic_mounting-done-restart = Retourner au début
onboarding-automatic_mounting-mounting_reset-title = Réinitialisation de l'alignement
onboarding-automatic_mounting-mounting_reset-step-0 = 1. Accroupissez-vous dans une pose de "ski" avec les jambes pliées, le haut du corps incliné vers l'avant et les bras pliés.
@@ -677,6 +743,24 @@ onboarding-automatic_mounting-put_trackers_on-title = Enfilez vos capteurs
onboarding-automatic_mounting-put_trackers_on-description = Pour calibrer l'alignement, nous allons utiliser les capteurs que vous venez d'attribuer.
onboarding-automatic_mounting-put_trackers_on-next = J'ai tous mes capteurs
## Tracker proportions method choose
onboarding-choose_proportions = Quelle méthode de calibration des proportions utiliser ?
# Multiline string
onboarding-choose_proportions-description =
Les proportions corporelles sont utilisées pour connaître les mesures de votre corps. Elles sont nécéssaires pour calculer les positions des capteurs.
Lorsque les proportions de votre corps ne correspondent pas à celles enregistrées, la précision des capteurs sera moins bonne et vous remarquerez des problèmes tel que le patinage, le glissage ou votre corps ne correspondant pas bien à votre avatar.
onboarding-choose_proportions-auto_proportions = Proportions automatiques
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Recommendée
onboarding-choose_proportions-auto_proportions-description = Ceci estimera vos proportions en enregistrant un extrait de vos mouvements et en le faisant traiter par un algorithme
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-file_type = Fichier de proportions
## Tracker manual proportions setup
onboarding-manual_proportions-back = Revenir au didacticiel de réinitialisation
@@ -706,7 +790,7 @@ onboarding-automatic_proportions-requirements-description =
Votre casque envoie sa position au serveur SlimeVR (cela signifie généralement que SteamVR est ouvert et connecté à SlimeVR en utilisant le driver SteamVR de SlimeVR).
onboarding-automatic_proportions-requirements-next = J'ai lu les exigences
onboarding-automatic_proportions-start_recording-title = Préparez-vous à bouger
onboarding-automatic_proportions-start_recording-description = Nous allons maintenant enregistrer des poses et des mouvements spécifiques.
onboarding-automatic_proportions-start_recording-description = Nous allons maintenant enregistrer quelques positions et mouvements spécifiques. Ceux-ci seront inscris sur lécran suivant. Soyez prêt à commencer dès que vous appuyez sur le bouton !
onboarding-automatic_proportions-start_recording-next = Commencer l'enregistrement
onboarding-automatic_proportions-recording-title = Enregistrement
onboarding-automatic_proportions-recording-description-p0 = Enregistrement en cours...
@@ -727,14 +811,24 @@ onboarding-automatic_proportions-recording-timer =
*[other] { $time } secondes restantes
}
onboarding-automatic_proportions-verify_results-title = Vérifier les résultats
onboarding-automatic_proportions-verify_results-description = Les résultats ci-dessous vous semblent-ils corrects?
onboarding-automatic_proportions-verify_results-description = Les résultats ci-dessous vous semblent-ils corrects ?
onboarding-automatic_proportions-verify_results-results = Enregistrement des résultats
onboarding-automatic_proportions-verify_results-processing = Traitement du résultat
onboarding-automatic_proportions-verify_results-redo = Refaire l'enregistrement
onboarding-automatic_proportions-verify_results-confirm = Les résultats sont corrects
onboarding-automatic_proportions-done-title = Calibration terminée
onboarding-automatic_proportions-done-description = Votre calibration est terminée!
onboarding-automatic_proportions-done-description = La calibration de vos proportions est terminée !
## Home
home-no_trackers = Aucun capteur détecté ou attribué
## Status system
status_system-StatusTrackerReset = Il est recommandé d'effectuer une réinitialisation complète vu que un ou plusieurs capteurs sont ne sont pas ajustés.
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] Impossible de se connecter au SlimeVR Feeder App.
*[other] Impossible de se connecter à SteamVR via le pilote SlimeVR.
}
status_system-StatusTrackerError = Le capteur { $trackerName } a une erreur.

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 = Connessione al server in corso
websocket-connection_lost = Connessione con il server persa. Tentativo di riconnessione in corso...
## Update notification
version_update-title = Nuova versione disponibile: { $version }
version_update-description = Cliccando su "{ version_update-update }" si scaricherà il programma di installazione di SlimeVR.
version_update-update = Aggiorna
version_update-close = Chiudi
## Tips
tips-find_tracker = Non sei sicurə quale tracker è quale? Agitalo e l'oggetto corrispondente sarà evidenziato.
tips-do_not_move_heels = Assicurati di non muovere i tuoi talloni durante la registrazione!
tips-file_select = Trascina qui i file da usare, o <u>sfoglia</u>.
tips-tap_setup = Puoi toccare lentamente 2 volte il tracker per sceglierlo invece di selezionarlo dal menu.
## Body parts
@@ -95,11 +100,16 @@ navbar-mounting = Calibrazione del posizionamento
navbar-onboarding = Installazione guidata
navbar-settings = Impostazioni
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Registra BVH
bvh-recording = Registrazione in corso...
## Tracking pause
tracking-unpaused = Pausa il tracking
tracking-paused = Riprendio il tracking
## Widget: Overlay settings
widget-overlay = Overlay
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = Ulteriori informazioni
widget-imu_visualizer = Rotazione
widget-imu_visualizer-rotation_raw = Non processato
widget-imu_visualizer-rotation_preview = Anteprima
widget-imu_visualizer-rotation_hide = Nascondi
## Tracker status
@@ -134,7 +145,7 @@ tracker-status-busy = Occupato
tracker-status-error = Errore
tracker-status-disconnected = Disconnesso
tracker-status-occluded = Ostruito
tracker-status-ok = Connesso
tracker-status-ok = OK
## Tracker status columns
@@ -160,10 +171,13 @@ tracker-rotation-back = Dietro
tracker-infos-manufacturer = Produttore
tracker-infos-display_name = Nome da visualizzare
tracker-infos-custom_name = Nome Personalizzato
tracker-infos-custom_name = Nome personalizzato
tracker-infos-url = URL del tracker
tracker-infos-version = Versione firmware
tracker-infos-hardware_rev = Versione hardware
tracker-infos-hardware_identifier = Hardware ID
tracker-infos-imu = Sensore IMU
tracker-infos-board_type = Scheda principale
## Tracker settings
@@ -171,17 +185,17 @@ tracker-settings-back = Torna alla lista dei tracker
tracker-settings-title = Impostazioni del tracker
tracker-settings-assignment_section = Assegnazione
tracker-settings-assignment_section-description = Definisce a che parte del corpo è assegnato il tracker.
tracker-settings-assignment_section-edit = Cambia assegnazione
tracker-settings-assignment_section-edit = Modifica assegnazione
tracker-settings-mounting_section = Posizionamento di montaggio
tracker-settings-mounting_section-description = Dove è posizionato il tracker?
tracker-settings-mounting_section-edit = Cambia posizionamento
tracker-settings-mounting_section-edit = Modifica posizionamento
tracker-settings-drift_compensation_section = Consenti compensazione per il drift
tracker-settings-drift_compensation_section-description = Questo tracker dovrebbe compensare per il drift quando la compensazione per il drift è abilitata?
tracker-settings-drift_compensation_section-edit = Consenti compensazione per il drift
# 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 = Nome del tracker
tracker-settings-name_section-description = Scegli un nomignolo carino :)
tracker-settings-name_section-description = Scegli un soprannome carino :)
tracker-settings-name_section-placeholder = Gamba destra di NightyQueer
## Tracker part card info
@@ -217,7 +231,7 @@ tracker_selection_menu-RIGHT_LOWER_LEG = { -tracker_selection-part } caviglia de
tracker_selection_menu-RIGHT_FOOT = { -tracker_selection-part } piede destro?
tracker_selection_menu-RIGHT_CONTROLLER = { -tracker_selection-part } controller destro?
tracker_selection_menu-CHEST = { -tracker_selection-part } petto?
tracker_selection_menu-WAIST = { -tracker_selection-part } vita?
tracker_selection_menu-WAIST = { -tracker_selection-part } girovita?
tracker_selection_menu-HIP = { -tracker_selection-part } bacino?
tracker_selection_menu-LEFT_SHOULDER = { -tracker_selection-part } spalla sinistra?
tracker_selection_menu-LEFT_UPPER_ARM = { -tracker_selection-part } parte superiore del braccio sinistro?
@@ -252,6 +266,7 @@ settings-sidebar-fk_settings = Impostazioni di traking
settings-sidebar-gesture_control = Controllo con gesti
settings-sidebar-interface = Interfaccia
settings-sidebar-osc_router = Router OSC
settings-sidebar-osc_trackers = Tracker OSC per VRChat
settings-sidebar-utils = Strumenti
settings-sidebar-serial = Console seriale
@@ -279,10 +294,10 @@ settings-general-tracker_mechanics = Comportamento del tracker
settings-general-tracker_mechanics-filtering = Filtro movimenti
# This also cares about multilines
settings-general-tracker_mechanics-filtering-description =
Scegli la tipologia di filtraggio movimenti per il tuo tracker.
Scegli la tipologia di filtro per il tuo tracker.
Predizione anticipa i movimenti, mentre Attenuazione attenua movimenti eccessivi.
settings-general-tracker_mechanics-filtering-type = Tipologia di filtraggio
settings-general-tracker_mechanics-filtering-type-none = Non usare alcun filtraggio
settings-general-tracker_mechanics-filtering-type = Tipologia di filtro
settings-general-tracker_mechanics-filtering-type-none = Non usare alcun filtro
settings-general-tracker_mechanics-filtering-type-none-description = Usa le rotazioni così come sono. Non eseguirà alcun filtro.
settings-general-tracker_mechanics-filtering-type-smoothing = Attenuazione
settings-general-tracker_mechanics-filtering-type-smoothing-description = Attenua movimenti eccessivi ma aggiunge ritardo.
@@ -310,7 +325,7 @@ settings-general-fk_settings-leg_tweak-floor_clip = Compenetrazione pavimento
settings-general-fk_settings-leg_tweak-skating_correction = Correzione slittamento
settings-general-fk_settings-leg_tweak-toe_snap = Dita dei piedi piantate
settings-general-fk_settings-leg_tweak-foot_plant = Piedi piantati
settings-general-fk_settings-leg_tweak-skating_correction-amount = Forza fattore di correzione pattinaggio
settings-general-fk_settings-leg_tweak-skating_correction-amount = Forza fattore di correzione slittamento
settings-general-fk_settings-leg_tweak-skating_correction-description = "Correzione slittamento" corregge l'effetto che fa sembrare che pattini sul ghiaccio, ma può peggiorare la precisione di certi movimenti. Quando abiliti questa funzione é necessario eseguire un reset completo e ri-calibrazione in gioco per il corretto funzionamento.
settings-general-fk_settings-leg_tweak-floor_clip-description = "Compenetrazione pavimento" può ridurre o anche eliminare completamente la compenetrazione con il pavimento. Quando abiliti questa funzione é necessario eseguire un reset completo e ri-calibrazione in gioco per il corretto funzionamento.
settings-general-fk_settings-leg_tweak-toe_snap-description = "Dita dei piedi piantate" prova ad indovinare la rotazione dei tuoi piedi quando non stai usando dei tracker per i piedi.
@@ -362,7 +377,8 @@ settings-general-interface-serial_detection-label = Rilevazione nuovi dispositiv
settings-general-interface-feedback_sound = Suono di feedback
settings-general-interface-feedback_sound-description = Questa opzione riprodurrà un suono quando viene effettuato un reset
settings-general-interface-feedback_sound-label = Suono di feedback
settings-general-interface-feedback_sound-volume = Volume del suono si feedback
settings-general-interface-feedback_sound-volume = Volume del suono di feedback
settings-general-interface-theme = Colore di tema
settings-general-interface-lang = Seleziona la lingua
settings-general-interface-lang-description = Seleziona la lingua che vuoi utilizzare
settings-general-interface-lang-placeholder = Seleziona la lingua da utilizzare
@@ -437,7 +453,7 @@ settings-osc-vrchat-network-address-placeholder = Indirizzo IP di VRChat
settings-osc-vrchat-network-trackers = Tracker
settings-osc-vrchat-network-trackers-description = Attiva o disattiva l'invio e la ricezione dei dati
settings-osc-vrchat-network-trackers-chest = Petto
settings-osc-vrchat-network-trackers-waist = Girovita
settings-osc-vrchat-network-trackers-hip = Bacino
settings-osc-vrchat-network-trackers-knees = Ginocchia
settings-osc-vrchat-network-trackers-feet = Piedi
settings-osc-vrchat-network-trackers-elbows = Gomiti
@@ -510,14 +526,29 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = Torna alla calibrazione posizionamento
onboarding-reset_tutorial = Tutorial di reset
onboarding-reset_tutorial-description = Questa funzionalità non è completa, premi continua
onboarding-reset_tutorial-skip = Salta passaggio
# Cares about multiline
onboarding-reset_tutorial-0 =
Tocca { $taps } volte il tracker evidenziato per eseguire il reset orientamento
Ciò farà sì che i tracker siano rivolti nella stessa direzione del tuo HMD.
# Cares about multiline
onboarding-reset_tutorial-1 =
Tocca { $taps } volte il tracker evidenziato per eseguire il reset completo.
Devi stare in piedi drittə per questo (I-pose). C'è un ritardo di 3 secondi (configurabile) prima che accada effettivamente.
Questo ripristinerà completamente la posizione e la rotazione di tutti i tuoi tracker. Dovrebbe risolvere la maggior parte dei problemi.
# Cares about multiline
onboarding-reset_tutorial-2 =
Tocca { $taps } volte il tracker evidenziato per eseguire il reset posizionamento.
Il reset posizionamento aiuta su come i tracker vengono effettivamente posizionati su di te, quindi se li hai spostati accidentalmente e hai cambiato il modo in cui sono orientati di una grande quantità, questo aiuterà.
Devi essere in posa come se stessi sciando come mostrato nella procedura guidata di posizionamento automatico e ha un ritardo di 3 secondi (configurabile) prima che venga attivato.
## Setup start
onboarding-home = Benvenuti a SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
Portiamo full-body tracking
a tuttə
onboarding-home-start = Prepariamoci!
## Enter VR part of setup
@@ -531,7 +562,7 @@ onboarding-enter_vr-ready = Sono prontə!
onboarding-done-title = È tutto pronto!
onboarding-done-description = Goditi la tua esperienza di full-body tracking
onboarding-done-close = Chiudi la guida
onboarding-done-close = Chiudi la configurazione
## Tracker connection setup
@@ -544,7 +575,7 @@ onboarding-connect_tracker-usb = Tracker USB
onboarding-connect_tracker-connection_status-none = Ricerca dei tracker in corso
onboarding-connect_tracker-connection_status-serial_init = Connessione al dispositivo seriale in corso
onboarding-connect_tracker-connection_status-provisioning = Invio credenziali Wi-Fi in corso
onboarding-connect_tracker-connection_status-connecting = Invio credenziali Wi-Fi in corso.
onboarding-connect_tracker-connection_status-connecting = Tentativo di connessione al Wi-Fi in corso
onboarding-connect_tracker-connection_status-looking_for_server = Ricerca del server in corso
onboarding-connect_tracker-connection_status-connection_error = Impossibile connettersi al Wi-Fi
onboarding-connect_tracker-connection_status-could_not_find_server = Impossibile trovare il server
@@ -562,6 +593,14 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = Ho collegato tutti i miei tracker
## Tracker calibration tutorial
onboarding-calibration_tutorial = Tutorial di calibrazione IMU
onboarding-calibration_tutorial-subtitle = Ciò aiuterà a ridurre il drift del tracker!
## Tracker assignment tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = Torna alle credenziali Wi-Fi
@@ -571,10 +610,10 @@ onboarding-assign_trackers-description = Scegliamo quale tracker va dove. Fare c
# $assigned (Number) - Trackers that have been assigned a body part
# $trackers (Number) - Trackers connected to the server
onboarding-assign_trackers-assigned =
{ $assigned } of { $trackers ->
[one] 1 tracker
*[other] { $trackers } trackers
} assigned
{ $trackers ->
[one] { $assigned } di 1 tracker assegnato
*[other] { $assigned } di { $trackers } tracker assegnati
}
onboarding-assign_trackers-advanced = Mostra impostazioni avanzate di assegnazione
onboarding-assign_trackers-next = Ho assegnato tutti i miei tracker
@@ -646,6 +685,18 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] Il girovita è assegnato, ma una parte del corpo sconosciuta non ha un tracker assegnato!
}
## Tracker mounting method choose
onboarding-choose_mounting = Quale metodo di calibrazione del posizionamento vuoi usare?
onboarding-choose_mounting-auto_mounting = Posizionamento automatico
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = Raccomandato
onboarding-choose_mounting-auto_mounting-description = Questo processo identificherá automaticamente le direzioni per la posizione di montaggio di tutti i traker facendo 2 pose
onboarding-choose_mounting-manual_mounting = Posizionamento manuale
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = Se sai cosa stai facendo
onboarding-choose_mounting-manual_mounting-description = Questo processo ti lascerá scegliere manualmente le direzioni per la posizione di montaggio di tutti i tracker
## Tracker manual mounting setup
onboarding-manual_mounting-back = Torna indietro per entrare in VR
@@ -659,7 +710,7 @@ onboarding-manual_mounting-next = Passo successivo
onboarding-automatic_mounting-back = Torna indietro per entrare in VR
onboarding-automatic_mounting-title = Calibrazione posizionamento
onboarding-automatic_mounting-description = Affinché i tracker di SlimeVR funzionino, dobbiamo configurare una rotazione di posizione di montaggio ai tuoi tracker per allinearli con la posizione di montaggio del tuo tracker fisico.
onboarding-automatic_mounting-manual_mounting = Imposta posizione manualmente
onboarding-automatic_mounting-manual_mounting = Posizionamento manuale
onboarding-automatic_mounting-next = Passo successivo
onboarding-automatic_mounting-prev_step = Passaggio precedente
onboarding-automatic_mounting-done-title = Rotazione delle posizioni di montaggio calibrate.
@@ -675,6 +726,18 @@ onboarding-automatic_mounting-put_trackers_on-title = Indossa i tuoi tracker
onboarding-automatic_mounting-put_trackers_on-description = Per calibrare le rotazioni delle posizioni di montaggio useremo i tracker che hai appena assegnato. Indossa tutti i tuoi tracker, puoi vedere quali sono quali nella figura a destra.
onboarding-automatic_mounting-put_trackers_on-next = Sto indossando tutti i miei tracker
## Tracker proportions method choose
onboarding-choose_proportions = Quale metodo di calibrazione delle proporzioni vuoi usare?
onboarding-choose_proportions-auto_proportions = Proporzioni automatiche
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Raccomandato
onboarding-choose_proportions-auto_proportions-description = Questo processo indovinerá le tue proporzioni del corpo registrando alcuni specifici movimenti che sono poi elaborati tramite un algoritmo
onboarding-choose_proportions-manual_proportions = Proporzioni manuali
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = Per piccole modifiche
onboarding-choose_proportions-manual_proportions-description = Questo processo ti permetterà di regolare manualmente le proporzioni del corpo modificandole direttamente.
## Tracker manual proportions setup
onboarding-manual_proportions-back = Torna al tutorial di reset
@@ -688,7 +751,7 @@ onboarding-manual_proportions-ratio = Regolazione tramite gruppi di rapporti
onboarding-automatic_proportions-back = Torna al tutorial di reset
onboarding-automatic_proportions-title = Misura il tuo corpo
onboarding-automatic_proportions-description = Affinché i tracker di SlimeVR funzionino dobbiamo conoscere la lunghezza dei tuoi arti. Questa breve calibrazione le misurerà per te.
onboarding-automatic_proportions-manual = Calibrazione manuale
onboarding-automatic_proportions-manual = Proporzioni manuali
onboarding-automatic_proportions-prev_step = Passaggio precedente
onboarding-automatic_proportions-put_trackers_on-title = Indossa i tuoi tracker
onboarding-automatic_proportions-put_trackers_on-description = Per calibrare le tue proporzioni useremo i tracker che hai appena assegnato. Indossa tutti i tuoi tracker, puoi vedere quali sono quali nella figura a destra.
@@ -735,3 +798,6 @@ onboarding-automatic_proportions-done-description = La calibrazione delle propor
## Home
home-no_trackers = Nessun tracker rilevato o assegnato
## 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,11 @@
websocket-connecting = サーバー接続中
websocket-connection_lost = サーバーへの接続が失われました。再接続を試みています...
## Update notification
version_update-update = アップデート
version_update-close = 閉じる
## Tips
tips-find_tracker = どのトラッカーがどれだかわからない?トラッカーを振ると、該当する項目がハイライトされます。
@@ -89,11 +91,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 = オーバーレイ設定
@@ -119,6 +124,7 @@ widget-developer_mode-more_info = 他情報
widget-imu_visualizer = 回転
widget-imu_visualizer-rotation_raw = 生
widget-imu_visualizer-rotation_preview = 生
widget-imu_visualizer-rotation_hide = 隠す
## Tracker status
@@ -413,7 +419,6 @@ 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-waist = 腰
settings-osc-vrchat-network-trackers-knees = 膝
settings-osc-vrchat-network-trackers-feet = 足
settings-osc-vrchat-network-trackers-elbows = 肘
@@ -497,6 +502,13 @@ onboarding-connect_tracker-connected_trackers =
} connected
onboarding-connect_tracker-next = すべてのトラッカーを接続しました
## Tracker calibration tutorial
onboarding-calibration_tutorial-status-calibrating = 校正中
## Tracker assignment tutorial
## Tracker assignment setup
onboarding-assign_trackers-back = Wi-Fi認証に戻る
@@ -518,6 +530,8 @@ onboarding-assign_trackers-next = すべてのトラッカーを割り当てま
## Tracker mounting method choose
# Italized text
onboarding-choose_mounting-auto_mounting-subtitle = おすすめされた
## Tracker manual mounting setup
@@ -550,6 +564,8 @@ onboarding-automatic_mounting-put_trackers_on-next = すべてのトラッカー
## Tracker proportions method choose
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = おすすめされた
## Tracker manual proportions setup
@@ -595,3 +611,6 @@ onboarding-automatic_proportions-done-description = ボディプロポーショ
## Home
home-no_trackers = トラッカーを検出できません。もしくは割り当てられていません。
## Status system

View File

@@ -363,6 +363,8 @@ 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 = 사용할 언어를 선택하세요
@@ -481,6 +483,12 @@ settings-osc-vmc-anchor_hip-label = 골반에 앵커 설정
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
@@ -508,10 +516,6 @@ onboarding-reset_tutorial-description = 이 기능은 아직 완성되지 않았
## Setup start
onboarding-home = SlimeVR에 어서오세요!
# This cares about multilines and it's centered!!
onboarding-home-description =
Bringing full-body tracking
to everyone
onboarding-home-start = 설정하러 가보죠!
## Enter VR part of setup
@@ -635,6 +639,18 @@ onboarding-assign_trackers-warning-WAIST =
*[other] 허리 트래커를 할당했다면 다른 몸통 트래커도 할당해야 해요.
}
## Tracker mounting method choose
onboarding-choose_mounting = 착용 방향을 정렬하기 위해 어떤 방법을 사용할래요?
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
onboarding-manual_mounting-back = VR 입장 페이지로 돌아가기
@@ -664,6 +680,18 @@ onboarding-automatic_mounting-put_trackers_on-title = 트래커를 착용해주
onboarding-automatic_mounting-put_trackers_on-description = 트래커의 착용 방향이 돌아가는 것을 보정하기 위해 방금 할당한 트래커를 사용할 거예요. 모든 트래커를 착용했다면 오른쪽 그림에서 어떤 트래커인지 확인할 수 있어요.
onboarding-automatic_mounting-put_trackers_on-next = 모든 트래커를 착용했어요
## Tracker proportions method choose
onboarding-choose_proportions = 신체 비율을 설정하 위해 어떤 방법을 사용할래요?
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 = 이렇게 하면 신체 비율을 직접 수정하여 수동으로 조절할 수 있어요
## Tracker manual proportions setup
onboarding-manual_proportions-back = 정렬 튜토리얼로 돌아가기
@@ -682,22 +710,32 @@ 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-preparation-title = 준비하기
onboarding-automatic_proportions-preparation-description = 여러분의 놀이 공간 안에 여러분의 바로 뒤에 의자를 놓으세요. 오토본 설정 중에 앉을 수 있도록 준비해주세요.
onboarding-automatic_proportions-preparation-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의 SteamVR 드라이버를 사용하여 SlimeVR에 연결되어 있어야 해요).
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 = REC
onboarding-automatic_proportions-recording-description-p0 = 기록하는 중...
onboarding-automatic_proportions-recording-description-p1 = 아래에 표시된 동작을 따라 하세요
onboarding-automatic_proportions-recording-steps-0 = 무릎을 몇 번 구부리세요
onboarding-automatic_proportions-recording-steps-1 = 의자에 앉았다가 일어서세요.
onboarding-automatic_proportions-recording-steps-2 = 상체를 왼쪽으로 비틀고 오른쪽으로 구부리세요.
onboarding-automatic_proportions-recording-steps-3 = 상체를 오른쪽으로 비틀고 왼쪽으로 구부리세요.
onboarding-automatic_proportions-recording-steps-4 = 타이머가 종료될 때까지 이리저리 움직여 보세요.
# 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 15)
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =
{ $time ->
*[other] { $time } 초 남음

View File

@@ -13,11 +13,19 @@
websocket-connecting = Verbinding maken met de server
websocket-connection_lost = Verbinding met de server verbroken. Opniew verbinding maken...
## Update notification
version_update-title = Nieuwe versie beschikbaar: { $version }
version_update-description = Als u op "Bijwerken" klikt, wordt het SlimeVR-installatieprogramma voor je gedownload.
version_update-update = Bijwerken
version_update-close = Sluiten
## Tips
tips-find_tracker = Weet je niet welke tracker welke is? Schud een tracker en het corresponderende item zal worden gemarkeerd.
tips-do_not_move_heels = Zorg ervoor dat je hielen niet bewegen tijdens de opname!
tips-file_select = Sleep bestanden naar hier om ze te gebruiken of <u>blader</u>.
tips-tap_setup = Je kan langzaam 2 keer op je tracker tikken om deze te kiezen in plaats van deze in het menu te selecteren.
## Body parts
@@ -126,6 +134,7 @@ widget-developer_mode-more_info = Meer informatie
widget-imu_visualizer = Rotatie
widget-imu_visualizer-rotation_raw = Rauw
widget-imu_visualizer-rotation_preview = Preview
widget-imu_visualizer-rotation_hide = Verbergen
## Tracker status
@@ -164,6 +173,9 @@ tracker-infos-custom_name = Aangepaste naam
tracker-infos-url = Tracker URL
tracker-infos-version = Firmware versie
tracker-infos-hardware_rev = Hardware revisie
tracker-infos-hardware_identifier = Hardware-id
tracker-infos-imu = IMU-sensor
tracker-infos-board_type = Mainbord
## Tracker settings
@@ -252,6 +264,7 @@ settings-sidebar-fk_settings = FK-instellingen
settings-sidebar-gesture_control = Tikbediening
settings-sidebar-interface = Interface
settings-sidebar-osc_router = OSC-router
settings-sidebar-osc_trackers = VRChat OSC Trackers
settings-sidebar-utils = Hulpmiddelen
settings-sidebar-serial = Serieel console
@@ -361,6 +374,7 @@ settings-general-interface-feedback_sound = Feedback geluid
settings-general-interface-feedback_sound-description = Speelt een geluid telkens de reset wordt uitgevoerd
settings-general-interface-feedback_sound-label = Feedback geluid
settings-general-interface-feedback_sound-volume = Feedback geluid volume
settings-general-interface-theme = Themakleur
settings-general-interface-lang = Selecteer taal
settings-general-interface-lang-description = Verander de standaardtaal die je wilt gebruiken.
settings-general-interface-lang-placeholder = Selecteer de te gebruiken taal
@@ -435,7 +449,7 @@ settings-osc-vrchat-network-address-placeholder = VRChat IP-adres
settings-osc-vrchat-network-trackers = Trackers
settings-osc-vrchat-network-trackers-description = Schakel het verzenden van specifieke trackers via OSC in en uit.
settings-osc-vrchat-network-trackers-chest = Borst
settings-osc-vrchat-network-trackers-waist = Taille
settings-osc-vrchat-network-trackers-hip = Heup
settings-osc-vrchat-network-trackers-knees = Knieën
settings-osc-vrchat-network-trackers-feet = Voeten
settings-osc-vrchat-network-trackers-elbows = Ellebogen
@@ -471,6 +485,7 @@ settings-osc-vmc-vrm-model_loaded =
}
settings-osc-vmc-vrm-file_select = Sleep een modelbestand naar hier om ze te gebruiken of <u>blader</u>.
settings-osc-vmc-anchor_hip = Heupverankering
settings-osc-vmc-anchor_hip-description = Veranker de tracking aan de heupen, handig voor zittende VTubing. Als u deze uitschakelt, laadt u een VRM-model.
settings-osc-vmc-anchor_hip-label = Heupverankering
## Setup/onboarding menu
@@ -478,6 +493,12 @@ settings-osc-vmc-anchor_hip-label = Heupverankering
onboarding-skip = Setupgids overslaan
onboarding-continue = Doorgaan
onboarding-wip = WIP
onboarding-previous_step = Vorige stap
onboarding-setup_warning =
<b>Waarschuwing:</b> De initiële setup is nodig voor een goede tracking ervaring,
het is aangeraden deze te volgen indien dit de eerste keer is dat je SlimeVR gebruikt.
onboarding-setup_warning-skip = Setupgids overslaan
onboarding-setup_warning-cancel = Doorgaan met setupgids
## Wi-Fi setup
@@ -505,10 +526,6 @@ onboarding-reset_tutorial-description = Deze stap is nog niet afgewerkt, druk ge
## Setup start
onboarding-home = Welkom bij SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
Maakt full-body tracking beschikbaar
voor iedereen!
onboarding-home-start = Laten we beginnen!
## Enter VR part of setup
@@ -553,6 +570,17 @@ onboarding-connect_tracker-connected_trackers =
} verbonden
onboarding-connect_tracker-next = Ik heb al mijn trackers verbonden
## Tracker calibration tutorial
onboarding-calibration_tutorial = Handleiding voor IMU-kalibratie
onboarding-calibration_tutorial-subtitle = Helpt met het verminderen van het driften van de trackers!
onboarding-calibration_tutorial-description = Elke keer dat je jouw trackers inschakelt, moeten ze even op een plat oppervlak rusten om te kalibreren. Leg al je trackers op een vlak oppervlak en <b>verplaats ze niet!</b>
onboarding-calibration_tutorial-calibrate = Al mijn trackers liggen neer
onboarding-calibration_tutorial-status-waiting = Ik wacht op jou
onboarding-calibration_tutorial-status-calibrating = Kalibreren
onboarding-calibration_tutorial-status-success = Aardig!
onboarding-calibration_tutorial-status-error = De tracker werd verplaatst
## Tracker assignment setup
onboarding-assign_trackers-back = Ga terug naar de instellingen voor WiFi-configuratie
@@ -571,6 +599,83 @@ onboarding-assign_trackers-next = Ik heb alle trackers toegewezen
## 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] De linkervoet is toegewezen, maar de linkerenkel, linkerdij en de borst, heup of taille moeten ook worden toegewezen!
[1] De linkervoet is toegewezen, maar het linkerdij en de borst, heup of taille moeten ook worden toegewezen!
[2] De linkervoet is toegewezen, maar de linkerenkel en de borst, heup of taille moeten ook worden toegewezen!
[3] De linkervoet is toegewezen, maar de borst, heup of taille moeten ook worden toegewezen!
[4] De linkervoet is toegewezen, maar de linkerenkel en linkerdij moeten ook worden toegewezen!
[5] De linkervoet is toegewezen, maar het linkerdij moet ook worden toegewezen!
[6] De linkervoet is toegewezen, maar de linkerenkel moet ook worden toegewezen!
*[other] De linkervoet is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_FOOT =
{ $unassigned ->
[0] De rechtervoet is toegewezen, maar de rechterenkel, rechterdij en de borst, heup of taille moeten ook worden toegewezen!
[1] De rechtervoet is toegewezen, maar het rechterdij en de borst, heup of taille moeten ook worden toegewezen!
[2] De rechtervoet is toegewezen, maar de rechterenkel en de borst, heup of taille moeten ook worden toegewezen!
[3] De rechtervoet is toegewezen, maar de borst, heup of taille moeten ook worden toegewezen!
[4] De rechtervoet is toegewezen, maar de rechterenkel en rechterdij moeten ook worden toegewezen!
[5] De rechtervoet is toegewezen, maar het rechterdij moet ook worden toegewezen!
[6] De rechtervoet is toegewezen, maar de rechterenkel moet ook worden toegewezen!
*[other] De rechtervoet is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_LOWER_LEG =
{ $unassigned ->
[0] De linkerenkel is toegewezen, maar de linkerdij en de borst, heup of taille moeten ook worden toegewezen!
[1] De linkerenkel is toegewezen, maar de borst, heup of taille moeten ook worden toegewezen!
[2] De linkerenkel is toegewezen, maar de linkerdij moet ook worden toegewezen!
*[other] De linkerenkel is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_LOWER_LEG =
{ $unassigned ->
[0] De rechterenkel is toegewezen, maar de rechterdij en de borst, heup of taille moeten ook worden toegewezen!
[1] De rechterenkel is toegewezen, maar de borst, heup of taille moeten ook worden toegewezen!
[2] De rechterenkel is toegewezen, maar de rechterdij moet ook worden toegewezen!
*[other] De rechterenkel is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-LEFT_UPPER_LEG =
{ $unassigned ->
[0] De linkerdij is toegewezen, maar de borst, heup of taille moeten ook worden toegewezen!
*[other] De linkerdij is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-RIGHT_UPPER_LEG =
{ $unassigned ->
[0] De rechterdij is toegewezen, maar de borst, heup of taille moeten ook worden toegewezen!
*[other] De rechterdij is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-HIP =
{ $unassigned ->
[0] De heup is toegewezen, maar de borst moet ook worden toegewezen!
*[other] De heup is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
# $unassigned (Number) - Bits are based on BodyAssignment.ASSIGNMENT_RULES order
onboarding-assign_trackers-warning-WAIST =
{ $unassigned ->
[0] De taille is toegewezen, maar de borst moet ook worden toegewezen!
*[other] De taille is toegewezen, maar het onbekend lichaamsdeel moet ook worden toegewezen!
}
## Tracker mounting method choose
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-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-description = Hiermee kunt u de montagerichting handmatig kiezen voor elke tracker
## Tracker manual mounting setup
@@ -601,12 +706,25 @@ onboarding-automatic_mounting-put_trackers_on-title = Doe je trackers aan
onboarding-automatic_mounting-put_trackers_on-description = Om bevestigingsrotaties te kalibreren, gaan we gebruik maken van de trackers die je net hebt toegewezen. Doe al je trackers aan, je kunt zien welke trackers welke zijn in de figuur rechts.
onboarding-automatic_mounting-put_trackers_on-next = Ik heb al mijn trackers aan
## Tracker proportions method choose
onboarding-choose_proportions = Welke verhoudingskalibratiemethode moet worden gebruikt?
onboarding-choose_proportions-auto_proportions = Automatische verhoudingen
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Aanbevolen
onboarding-choose_proportions-auto_proportions-description = We kunnen je verhoudingen proberen approximeren door middel van jouw bewegingen
onboarding-choose_proportions-manual_proportions = Handmatige lichaamsverhoudingen
# Italized text
onboarding-choose_proportions-manual_proportions-subtitle = Voor kleine details
onboarding-choose_proportions-manual_proportions-description = Hier kan je jouw verhoudingen handmatig aanpassen
## Tracker manual proportions setup
onboarding-manual_proportions-back = Ga terug naar de reset tutorial
onboarding-manual_proportions-title = Handmatige lichaamsverhoudingen
onboarding-manual_proportions-precision = Precisie-aanpassing
onboarding-manual_proportions-auto = Automatische kalibratie
onboarding-manual_proportions-ratio = Aanpassen via verhoudingen
## Tracker automatic proportions setup
@@ -619,6 +737,14 @@ onboarding-automatic_proportions-put_trackers_on-title = Doe je trackers aan
onboarding-automatic_proportions-put_trackers_on-description = Om je verhoudingen te kalibreren, gaan we gebruik maken van de trackers die je net hebt toegewezen. Doe al je trackers aan, je kunt zien welke trackers welke zijn in de figuur rechts.
onboarding-automatic_proportions-put_trackers_on-next = Ik heb al mijn trackers aan
onboarding-automatic_proportions-requirements-title = Vereisten
# Each line of text is a different list item
onboarding-automatic_proportions-requirements-description =
Je hebt in ieder geval genoeg trackers om je voeten te volgen (over het algemeen 5 trackers).
Je hebt je trackers en headset op.
Je draagt je trackers en headset.
Je trackers en headset zijn verbonden met de SlimeVR server.
Je trackers en headset werken goed binnen de SlimeVR server.
Je headset rapporteert positiegegevens aan de SlimeVR-server (dit betekent over het algemeen dat SteamVR wordt uitgevoerd en verbonden met SlimeVR met behulp van SlimeVR's SteamVR-stuurprogramma).
onboarding-automatic_proportions-requirements-next = Ik heb de vereisten gelezen
onboarding-automatic_proportions-start_recording-title = Zorg dat je klaar bent om te bewegen
onboarding-automatic_proportions-start_recording-description = We gaan nu enkele specifieke houdingen en bewegingen opnemen. Deze worden in het volgende scherm geprompt. Zorg dat je klaar bent om te beginnen als de knop wordt ingedrukt!
@@ -626,6 +752,14 @@ onboarding-automatic_proportions-start_recording-next = Start opname
onboarding-automatic_proportions-recording-title = REC
onboarding-automatic_proportions-recording-description-p0 = Opname bezig...
onboarding-automatic_proportions-recording-description-p1 = Voer de onderstaande bewegingen uit:
# Each line of text is a different list item
onboarding-automatic_proportions-recording-steps =
Sta rechtop, rol je hoofd in een cirkel.
Buig je rug naar voren en hurk. Kijk tijdens het hurken naar links en dan naar rechts.
Draai je bovenlichaam naar links (tegen de klok in) en reik dan naar beneden naar de grond.
Draai je bovenlichaam naar rechts (met de klok mee) en reik dan naar beneden naar de grond.
Rol je heupen in een cirkelvormige beweging alsof je een hoelahoep gebruikt.
Als er nog tijd over is voor de opname, kunt u deze stappen herhalen totdat deze is voltooid.
onboarding-automatic_proportions-recording-processing = Resultaat verwerken
# $time (Number) - Seconds left for the automatic calibration recording to finish (max 20)
onboarding-automatic_proportions-recording-timer =

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 = Łączenie z serwerem
websocket-connection_lost = Połączenie z serwerem zostało utracone. Próba ponownego połączenia...
## Update notification
version_update-title = Dostępna jest nowa wersja: { $version }
version_update-description = Kliknięcie „Aktualizuj” spowoduje pobranie instalatora SlimeVR.
version_update-update = Aktualizacja
version_update-close = Zamknij
## Tips
tips-find_tracker = Nie wiesz który tracker to który? Obracaj Trackerem , podczas obracania będzie sie on podświetlał w serwerze.
tips-do_not_move_heels = Upewnij się aby pięty pozostały w bezruchu podczas nagrywania.
tips-file_select = Przeciągnij i upuść pliki, których chcesz użyć, lub <u>przeglądaj</u>.
tips-tap_setup = Możesz powoli stuknąć 2 razy tracker, aby go wybrać, zamiast wybierać go z menu.
## Body parts
@@ -95,11 +100,16 @@ navbar-mounting = Kalibracja Pozycji
navbar-onboarding = Wstępna Konfiguracja
navbar-settings = Ustawienia
## Bounding volume hierarchy recording
## Biovision hierarchy recording
bvh-start_recording = Nagraj BVH
bvh-recording = Nagrywam...
## Tracking pause
tracking-unpaused = Wstrzymaj śledzenie
tracking-paused = Wznów śledzenie
## Widget: Overlay settings
widget-overlay = Overlay
@@ -126,6 +136,7 @@ widget-developer_mode-more_info = Więcej info
widget-imu_visualizer = Obrót
widget-imu_visualizer-rotation_raw = Raw
widget-imu_visualizer-rotation_preview = Podgląd
widget-imu_visualizer-rotation_hide = Ukryj
## Tracker status
@@ -164,6 +175,9 @@ tracker-infos-custom_name = Niestandardowa Nazwa
tracker-infos-url = Tracker URL
tracker-infos-version = Wersja Oprogramowania
tracker-infos-hardware_rev = Wersja Sprzętu
tracker-infos-hardware_identifier = Identyfikator sprzętu
tracker-infos-imu = Czujnik IMU
tracker-infos-board_type = Płyta główna
## Tracker settings
@@ -176,7 +190,7 @@ tracker-settings-mounting_section = Położenie Trackera
tracker-settings-mounting_section-description = Gdzie jest Tracker zamontowany?
tracker-settings-mounting_section-edit = Edytuj
tracker-settings-drift_compensation_section = Allow drift compensation
tracker-settings-drift_compensation_section-description = Should this tracker compensate for its drift when drift compensation is enabled?
tracker-settings-drift_compensation_section-description = Czy ten tracker powinien kompensować dryf, gdy kompensacja dryfu jest włączona?
tracker-settings-drift_compensation_section-edit = Allow drift compensation
# 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 = FK settings
settings-sidebar-gesture_control = Sterowanie gestami
settings-sidebar-interface = Interfejs
settings-sidebar-osc_router = OSC router
settings-sidebar-osc_trackers = Śledzenie VRChat OSC
settings-sidebar-utils = Narzędzia
settings-sidebar-serial = Konsola Seryjna
@@ -367,6 +382,7 @@ settings-general-interface-feedback_sound = Dźwięk Informacji
settings-general-interface-feedback_sound-description = Ta opcja odtworzy dźwięk, gdy reset zostanie uruchomiony
settings-general-interface-feedback_sound-label = Dźwięk Informacji
settings-general-interface-feedback_sound-volume = Poziom głośności sprzężenia zwrotnego
settings-general-interface-theme = Motyw kolorystyczny
settings-general-interface-lang = Wybierz Język
settings-general-interface-lang-description = Zmień podstawowy język jaki chcesz używać
settings-general-interface-lang-placeholder = Wybierz Język który będziesz używać
@@ -399,9 +415,9 @@ settings-osc-router = OSC router
settings-osc-router-description =
Przekaż wiadomości OSC z innego programu.
Przydatne na przykład do używania innego programu OSC z VRChat.
settings-osc-router-enable = Enable
settings-osc-router-enable-description = Przełącz przekazywanie wiadomości.
settings-osc-router-enable-label = Enable
settings-osc-router-enable = Zezwól
settings-osc-router-enable-description = Zezwól na przekazywanie wiadomości.
settings-osc-router-enable-label = Zezwól
settings-osc-router-network = Porty sieciowe
# This cares about multilines
settings-osc-router-network-description =
@@ -424,9 +440,9 @@ settings-osc-vrchat = VRChat OSC Trackers
settings-osc-vrchat-description =
Zmień ustawienia specyficzne dla VRChat, aby odbierać i wysyłać dane HMD
dane trackerów dla FBT (działa na samodzielnym Quest).
settings-osc-vrchat-enable = Enable
settings-osc-vrchat-enable-description = Przełącz wysyłanie i odbieranie danych.
settings-osc-vrchat-enable-label = Enable
settings-osc-vrchat-enable = Zezwól
settings-osc-vrchat-enable-description = Zezwól na wysyłanie i odbieranie danych.
settings-osc-vrchat-enable-label = Zezwól
settings-osc-vrchat-network = Porty sieciowe
settings-osc-vrchat-network-description = Ustaw porty do odbierania i wysyłania danych do VRChat.
settings-osc-vrchat-network-port_in =
@@ -441,7 +457,7 @@ settings-osc-vrchat-network-address-placeholder = VRChat ip address
settings-osc-vrchat-network-trackers = Trackers
settings-osc-vrchat-network-trackers-description = Przełącz wysyłanie określonych trackerów przez OSC.
settings-osc-vrchat-network-trackers-chest = Klatka piersiowa
settings-osc-vrchat-network-trackers-waist = Talia
settings-osc-vrchat-network-trackers-hip = Biodro
settings-osc-vrchat-network-trackers-knees = Kolana
settings-osc-vrchat-network-trackers-feet = Stopy
settings-osc-vrchat-network-trackers-elbows = Łokcie
@@ -514,14 +530,29 @@ 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-skip = Pomiń krok
# Cares about multiline
onboarding-reset_tutorial-0 =
Stuknij { $taps } razy podświetlony tracker, aby uruchomić reset odchylenia.
Spowoduje to, że trackery będą skierowane w tym samym kierunku, co Twój HMD.
# Cares about multiline
onboarding-reset_tutorial-1 =
Stuknij { $taps } razy podświetlony tracker, aby wywołać pełny reset.
Musisz stać, aby to zrobić (i-pozycja). Istnieje 3-sekundowe opóźnienie (konfigurowalne), zanim to nastąpi.
Spowoduje to całkowite zresetowanie pozycji i rotacji wszystkich trackerów. Powinien rozwiązać większość problemów.
# Cares about multiline
onboarding-reset_tutorial-2 =
Stuknij { $taps } razy podświetlony tracker, aby uruchomić reset montażu.
Resetowanie montażu pomaga w tym, w jaki sposób trackery są faktycznie zakładane na ciebie, więc jeśli przypadkowo je przeniosłeś i zmieniłeś ich orientację o dużą ilość, to pomoże.
Musisz być w pozie, jakbyś jechał na nartach, tak jak jest to pokazane w kreatorze automatycznego montażu, i masz 3-sekundowe opóźnienie (konfigurowalne), zanim zostanie uruchomione.
## Setup start
onboarding-home = Witamy w SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
Full-body tracking
dla każdego
onboarding-home-start = Zaczynajmny!
## Enter VR part of setup
@@ -568,6 +599,27 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = Połączyłem już wszystkie trackery
## Tracker calibration tutorial
onboarding-calibration_tutorial = Samouczek kalibracji IMU
onboarding-calibration_tutorial-subtitle = Pomoże to ograniczyć dryf trackera!
onboarding-calibration_tutorial-description = Za każdym razem, gdy włączasz trackery, muszą one chwilę polerzeć na płaskiej powierzchni, aby się skalibrować. Zróbmy to samo, klikając przycisk „Kalibruj”, <b>nie ruszaj ich!</b>
onboarding-calibration_tutorial-calibrate = Położyłem trackery na stole
onboarding-calibration_tutorial-status-waiting = Czekam na Ciebie
onboarding-calibration_tutorial-status-calibrating = Kalibracja
onboarding-calibration_tutorial-status-success = Nieźle!
onboarding-calibration_tutorial-status-error = Tracker został przeniesiony
## Tracker assignment tutorial
onboarding-assignment_tutorial = Jak przygotować Slime Tracker przed założeniem
onboarding-assignment_tutorial-first_step = 1. Umieść naklejkę z częścią ciała (jeśli ją posiadasz) na trackerze według własnego uznania
# This text has a character limit of around 11 characters, so please keep it short
onboarding-assignment_tutorial-sticker = Naklejka
onboarding-assignment_tutorial-second_step = 2. Przymocuj pasek do trackera, utrzymując stronę paska z haczykiem i pętelką w następującej orientacji:
onboarding-assignment_tutorial-second_step-continuation = Strona z haczykiem i pętelką dla przedłużenia powinna być w tej orientacji:
onboarding-assignment_tutorial-done = Umieszczam naklejki i paski!
## Tracker assignment setup
onboarding-assign_trackers-back = Cofnij się do ustawień Wi-Fi
@@ -654,6 +706,20 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] Talia jest przypisana, ale potrzebujesz również nieznanej nieprzypisanej części ciała!
}
## Tracker mounting method choose
onboarding-choose_mounting = Jakiej metody kalibracji montażu użyć?
# Multiline text
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-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-description = Umożliwi to ręczne wybranie kierunku montażu dla każdego trackera
## Tracker manual mounting setup
onboarding-manual_mounting-back = Cofnij się żeby wejść do VR
@@ -683,6 +749,24 @@ onboarding-automatic_mounting-put_trackers_on-title = Załóż trackery
onboarding-automatic_mounting-put_trackers_on-description = Aby skalibrować rotacje, użyjemy trackerów które przed chwilą przypisałeś. Załóż wszystkie trackery, będziesz widział który to który na postaci po prawej.
onboarding-automatic_mounting-put_trackers_on-next = Mam wszystkie trackery założone
## Tracker proportions method choose
onboarding-choose_proportions = Jakiej metody kalibracji proporcji użyć?
# Multiline string
onboarding-choose_proportions-description =
Proporcje ciała służą do poznania wymiarów twojego ciała. Są wymagane do obliczenia pozycji trackerów.
Kiedy proporcje twojego ciała nie odpowiadają zapisanym, precyzja śledzenia będzie gorsza i zauważysz takie rzeczy, jak jazda na łyżwach lub ślizganie się, lub twoje ciało nie pasuje dobrze do twojego awatara.
onboarding-choose_proportions-auto_proportions = Proporcje automatyczne
# Italized text
onboarding-choose_proportions-auto_proportions-subtitle = Zalecana
onboarding-choose_proportions-auto_proportions-description = To odgadnie twoje proporcje, rejestrując próbkę twoich ruchów i przepuszczając ją przez sztuczną inteligencję
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-file_type = Proporcje ciała
## Tracker manual proportions setup
onboarding-manual_proportions-back = Wróć do samouczka resetowania
@@ -746,3 +830,13 @@ onboarding-automatic_proportions-done-description = Twoja kalibracja ciała zost
## Home
home-no_trackers = Nie wykryto trackerów
## Status system
status_system-StatusTrackerReset = Zaleca się wykonanie pełnego resetu, ponieważ jeden lub więcej trackerów nie jest wyregulowanych.
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] Nie można połączyć się z aplikacją SlimeVR Feeder.
*[other] Nie można połączyć się ze SteamVR przez sterownik SlimeVR.
}
status_system-StatusTrackerError = Moduł śledzący { $trackerName } ma błąd.

View File

@@ -366,6 +366,8 @@ 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 = Выберите язык для использования
@@ -440,7 +442,6 @@ 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-waist = Талия
settings-osc-vrchat-network-trackers-knees = Колени
settings-osc-vrchat-network-trackers-feet = Ступни
settings-osc-vrchat-network-trackers-elbows = Локти
@@ -484,6 +485,11 @@ settings-osc-vmc-anchor_hip-label = Привязать к бедрам
onboarding-skip = Пропустить установку
onboarding-continue = Продолжить
onboarding-wip = В разработке
onboarding-previous_step = Предыдущий шаг
onboarding-setup_warning =
<b>Предупреждение.</b> Для правильного отслеживания требуется первоначальная настройка,
это необходимо, если вы впервые используете SlimeVR.
onboarding-setup_warning-skip = Пропустить настройку
## Wi-Fi setup
@@ -511,10 +517,6 @@ onboarding-reset_tutorial-description = Эта функция не заверш
## Setup start
onboarding-home = Добро пожаловать в SlimeVR!
# This cares about multilines and it's centered!!
onboarding-home-description =
Обеспечение полного отслеживания тела
для всех
onboarding-home-start = Давайте все настроим!
## Enter VR part of setup
@@ -570,12 +572,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 ->
[one] 1 трекер
[few] { $amount } трекера
[many] { $amount } трекеров
*[other] { $amount } трекеров
} привязано
{ $trackers ->
[one] { $assigned } из 1 трекер привязано
[few] { $assigned } из { $trackers } трекера привязано
[many] { $assigned } из { $trackers } трекеров привязано
*[other] { $assigned } из { $trackers } трекеров привязано
}
onboarding-assign_trackers-advanced = Показать дополнительные места привязки
onboarding-assign_trackers-next = Я привязал все трекеры
@@ -647,6 +649,9 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] Талия назначена, но вам нужно, чтобы неизвестная неназначенная часть тела также была назначена!
}
## Tracker mounting method choose
## Tracker manual mounting setup
onboarding-manual_mounting-back = Вернуться чтобы войти в VR
@@ -676,6 +681,9 @@ onboarding-automatic_mounting-put_trackers_on-title = Наденьте ваши
onboarding-automatic_mounting-put_trackers_on-description = Чтобы откалибровать повороты крепления, мы будем использовать трекеры, которые вы только что назначили. Включите все свои трекеры, вы можете увидеть, какие из них какие на рисунке справа.
onboarding-automatic_mounting-put_trackers_on-next = Я включил и надел все свои трекеры
## Tracker proportions method choose
## Tracker manual proportions setup
onboarding-manual_proportions-back = Вернутся к началу обучения
@@ -694,22 +702,14 @@ 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-preparation-title = Подготовка
onboarding-automatic_proportions-preparation-description = Поставьте стул прямо позади себя в вашем игровом пространстве. Будьте готовы сесть во время автоматической настройки костей.
onboarding-automatic_proportions-preparation-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 = Сделайте эти движения:
onboarding-automatic_proportions-recording-steps-0 = Согните колени несколько раз.
onboarding-automatic_proportions-recording-steps-1 = Сядьте на стул, затем встаньте.
onboarding-automatic_proportions-recording-steps-2 = Поверните верхнюю часть туловища влево, затем наклонитесь вправо.
onboarding-automatic_proportions-recording-steps-3 = Поверните верхнюю часть туловища вправо, затем наклонитесь влево.
onboarding-automatic_proportions-recording-steps-4 = Покачайтесь, пока таймер не закончится.
onboarding-automatic_proportions-recording-processing = Обработка результата...
# $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] { $time } секунда

View File

@@ -0,0 +1,157 @@
### 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!
# 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 = กำลังเชื่อมต่อกับเซิร์ฟเวอร์
## Update notification
## Tips
## Body parts
## Proportions
## Tracker reset buttons
## Serial detection stuff
## Navigation bar
## Bounding volume hierarchy recording
## Widget: Overlay settings
## Widget: Drift compensation
## Widget: Developer settings
## Widget: IMU Visualizer
## Tracker status
## Tracker status columns
## Tracker rotation
## Tracker information
## Tracker settings
## Tracker part card info
## Body assignment menu
## Tracker assignment menu
## Mounting menu
## Sidebar settings
## SteamVR settings
## Tracker mechanics
## FK/Tracking settings
## Gesture control settings (tracker tapping)
## Interface settings
## Serial settings
## OSC router settings
## OSC VRChat settings
## VMC OSC settings
## Setup/onboarding menu
## Wi-Fi setup
## Mounting setup
## Setup start
## Enter VR part of setup
## Setup done
## Tracker connection setup
## Tracker calibration 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
## Home

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 = 点击“更新”将为您下载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 = 原始旋转
widget-imu_visualizer-rotation_preview = 预览
widget-imu_visualizer-rotation_hide = 隐藏
## Tracker status
@@ -164,6 +175,9 @@ tracker-infos-custom_name = 自定义名称
tracker-infos-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 = 串口控制台
@@ -318,9 +333,9 @@ 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 = 手臂 FK
settings-general-fk_settings-arm_fk-description = 更改手臂的追踪方式
settings-general-fk_settings-arm_fk-force_arms = 强制从头显获得数据
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 = 脊柱延伸
@@ -364,6 +379,7 @@ 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 = 选择要使用的语言
@@ -381,8 +397,8 @@ 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>
<b>警告:</b> 这会将踪器重置为出厂设置。
这意味着 Wi-Fi 凭据和校准数据 <b>都将丢失!</b>
settings-serial-factory_reset-warning-ok = 我已知晓
settings-serial-factory_reset-warning-cancel = 取消
settings-serial-get_infos = 获取信息
@@ -438,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 = 胸部
settings-osc-vrchat-network-trackers-waist =
settings-osc-vrchat-network-trackers-hip =
settings-osc-vrchat-network-trackers-knees = 膝盖
settings-osc-vrchat-network-trackers-feet = 脚部
settings-osc-vrchat-network-trackers-elbows = 肘部
@@ -510,15 +526,30 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = 返回到佩戴校准
onboarding-reset_tutorial = 重置教程
onboarding-reset_tutorial-description = 此功能尚未开发完成,请继续就好
onboarding-reset_tutorial-description = 跟踪器在使用时可能会由于IMU的偏航漂移而失准或者可能因为您对它们进行了物理上的移动。您有几种方法来解决这个问题。
onboarding-reset_tutorial-skip = 跳过步骤
# Cares about multiline
onboarding-reset_tutorial-0 =
敲击 { $taps } 次高亮显示的追踪器以触发航向轴重置。
这将使追踪器朝向与您的头显相同的方向。
# Cares about multiline
onboarding-reset_tutorial-1 =
敲击 { $taps } 次高亮显示的追踪器以触发完整重置。
此功能需要你站直i-pose后使用。 在重置实际发生前有 3 秒延迟(可配置)。
这将完全重置所有追踪器的位置和旋转,应该能解决大多数问题。
# Cares about multiline
onboarding-reset_tutorial-2 =
敲击 { $taps } 次高亮显示的追踪器以触发佩戴重置。
佩戴重置能对追踪器实际的配戴方式进行调整,所以如果你不小心移动了追踪器并将它们的佩戴方向改变了很多,这个功能将有所帮助。
你需要摆出一个像滑雪那样的姿势,就像在运行自动设置佩戴向导时做的那样,在重置实际发生前有 3 秒延迟(可配置)。
## Setup start
onboarding-home = 欢迎来到 SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
将全身追踪
带给每一个人
onboarding-home-start = 我准备好了!
## Enter VR part of setup
@@ -562,6 +593,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 = 每次开启追踪器时,它们都需要在平坦的表面上放置片刻以进行自校准。你可以通过点击“校准”按钮来手动校准, <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 凭据设置
@@ -642,12 +694,26 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] 腰部 已分配,但您还需要分配 未知未分配身体部位!
}
## 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 = 这将需要你做2个动作以自动检测所有追踪器的佩戴方向
onboarding-choose_mounting-manual_mounting = 手动设置佩戴方向
# Italized text
onboarding-choose_mounting-manual_mounting-subtitle = 如果你清楚自己在做什么
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-auto_mounting = 自动设置佩戴方向
onboarding-manual_mounting-next = 下一步
## Tracker automatic mounting setup
@@ -671,6 +737,24 @@ onboarding-automatic_mounting-put_trackers_on-title = 穿戴好追踪器
onboarding-automatic_mounting-put_trackers_on-description = 为了校准佩戴方向,我们将使用你刚才分配的追踪器。戴上你所有的追踪器,你可以在右边的图中看到哪个追踪器对应哪个。
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 = 这将录制你的运动样本并通过AI来猜测你的身体比例
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-file_type = 身体比例文件
## Tracker manual proportions setup
onboarding-manual_proportions-back = 返回重置教程
@@ -707,12 +791,12 @@ 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 = 剩余{ $time }秒
@@ -728,3 +812,13 @@ onboarding-automatic_proportions-done-description = 你的身体比例校准已
## Home
home-no_trackers = 未检测到或未分配追踪器
## Status system
status_system-StatusTrackerReset = 建议执行完整重置,因为有至少一个追踪器未被调整。
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] 尚未连接到 SlimeVR Feeder App
*[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 = 按下「更新」將為您下載 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
@@ -79,7 +84,7 @@ reset-yaw = 左右偏擺重置
## Serial detection stuff
serial_detection-new_device-p0 = 偵測到了新的串列埠裝置!
serial_detection-new_device-p1 = 輸入你的 Wi-Fi 網路名稱與密碼
serial_detection-new_device-p1 = 輸入你的 Wi-Fi 認證資訊
serial_detection-new_device-p2 = 請選擇你想對它做什麼
serial_detection-open_wifi = 連線到 Wi-Fi
serial_detection-open_serial = 開啟串列埠終端
@@ -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 = 原始旋轉
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 = 追蹤設定
settings-sidebar-gesture_control = 手勢控制
settings-sidebar-interface = 使用者介面
settings-sidebar-osc_router = OSC 路由
settings-sidebar-osc_trackers = VRChat OSC 追蹤器
settings-sidebar-utils = 工具
settings-sidebar-serial = 串列埠終端
@@ -319,8 +334,8 @@ 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-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 = 脊椎延伸
@@ -364,6 +379,7 @@ 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 = 選擇要使用的語言
@@ -404,10 +420,10 @@ settings-osc-router-network-description =
可以與 SlimeVR 伺服器中使用的其他埠號相同。
settings-osc-router-network-port_in =
.label = 輸入埠
.placeholder = 輸入埠
.placeholder = 輸入埠預設9002
settings-osc-router-network-port_out =
.label = 輸出埠
.placeholder = 輸出埠
.placeholder = 輸出埠預設9000
settings-osc-router-network-address = 網路地址
settings-osc-router-network-address-description = 設置用來發送資料的位址。
settings-osc-router-network-address-placeholder = IPV4 地址
@@ -417,8 +433,8 @@ settings-osc-router-network-address-placeholder = IPV4 地址
settings-osc-vrchat = VRChat OSC 追蹤器
# This cares about multilines
settings-osc-vrchat-description =
此處可更改 VRChat 專用的設定以取得頭戴顯示器的資料,並傳送
追蹤器資料以進行全身追蹤。(也適用於 Quest 單機版本)
此處可更改 VRChat 專用的設定以取得頭戴顯示器的資料,並傳送追蹤器
資料以進行全身追蹤,不須透過 SteamVR例如 Quest 單機版本)
settings-osc-vrchat-enable = 啟用
settings-osc-vrchat-enable-description = 切換資料的傳送和接收。
settings-osc-vrchat-enable-label = 啟用
@@ -426,17 +442,17 @@ settings-osc-vrchat-network = 連接埠
settings-osc-vrchat-network-description = 設定與 VRChat 監聽和傳送資料的連接埠。
settings-osc-vrchat-network-port_in =
.label = 輸入埠
.placeholder = 輸入埠(預設 9001
.placeholder = 輸入埠(預設9001
settings-osc-vrchat-network-port_out =
.label = 輸出埠
.placeholder = 輸出埠(預設 9000
.placeholder = 輸出埠(預設9000
settings-osc-vrchat-network-address = 網路位址
settings-osc-vrchat-network-address-description = 設定用來發送資料到 VRChat 的位址(請檢查裝置的 Wi-Fi 設定)。
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-waist =
settings-osc-vrchat-network-trackers-hip =
settings-osc-vrchat-network-trackers-knees = 膝蓋
settings-osc-vrchat-network-trackers-feet = 腳部
settings-osc-vrchat-network-trackers-elbows = 肘部
@@ -482,19 +498,19 @@ onboarding-continue = 繼續
onboarding-wip = 施工中
onboarding-previous_step = 上一步
onboarding-setup_warning =
<b>警告:</b>需要設定才能進行良好的追蹤
如果這是您是第一次使用SlimeVR請繼續進行設定。
<b>警告:</b>若要有良好的追蹤效果,必須進行初始設定
如果這是您是第一次使用 SlimeVR請繼續進行設定。
onboarding-setup_warning-skip = 跳過設定
onboarding-setup_warning-cancel = 繼續設定
## Wi-Fi setup
onboarding-wifi_creds-back = 返回簡介
onboarding-wifi_creds = 輸入 Wi-Fi 網路名稱與密碼
onboarding-wifi_creds = 輸入 Wi-Fi 認證資訊
# This cares about multilines
onboarding-wifi_creds-description =
追蹤器將使用這些資訊連線到 Wi-Fi
請使用目前連線到 Wi-Fi 的網路名稱與密碼
追蹤器將使用該認證資訊以進行無線連接,
請使用目前連接中的認證資訊。
onboarding-wifi_creds-skip = 跳過 Wi-Fi 設定
onboarding-wifi_creds-submit = 送出!
onboarding-wifi_creds-ssid =
@@ -508,16 +524,31 @@ onboarding-wifi_creds-password =
onboarding-reset_tutorial-back = 返回到配戴校正
onboarding-reset_tutorial = 重置教學
onboarding-reset_tutorial-description = 此功能尚未開發完成,請點選繼續即可
onboarding-reset_tutorial-description = 使用追蹤器時會產生偏移,可能是因為慣性測量單元 (IMU) 會出現左右飄移,或是您移動了追蹤器所造成的。您有幾種方法來修正這個問題
onboarding-reset_tutorial-skip = 跳過本步驟
# Cares about multiline
onboarding-reset_tutorial-0 =
對所標記之追蹤器敲擊 { $taps } 次即可觸發左右偏擺重置。
追蹤器將會調整與頭戴顯示器所面對的方向一致。
# Cares about multiline
onboarding-reset_tutorial-1 =
對所標記之追蹤器敲擊 { $taps } 次即可觸發完整重置。
做此校正時必須站直,觸發 3 秒後(可修改)才會真正進行重置。
追蹤器的定位與旋轉將會被完全重置,應該可以解決大多數的問題。
# Cares about multiline
onboarding-reset_tutorial-2 =
對所標記之追蹤器敲擊 { $taps } 次即可觸發配戴重置。
配戴校正能對追蹤器實際的配戴方式進行調整,因此若您不小心移動到追蹤器,或是大幅度的變更配戴方向,這個功能會有所幫助。
做此校正時需要進行滑雪姿勢,如自動配戴校正的畫面所示。在觸發 3 秒後(可修改)才會真正進行重置。
## Setup start
onboarding-home = 歡迎來到 SlimeVR
# This cares about multilines and it's centered!!
onboarding-home-description =
將全身追蹤
帶給每一個人
onboarding-home-start = 我準備好了!
onboarding-home-start = 來開始設定吧!
## Enter VR part of setup
@@ -530,11 +561,11 @@ onboarding-enter_vr-ready = 我準備好了
onboarding-done-title = 都搞定啦!
onboarding-done-description = 享受你的全身追蹤體驗吧
onboarding-done-close = 關閉導引
onboarding-done-close = 關閉設定
## Tracker connection setup
onboarding-connect_tracker-back = 返回到 Wi-Fi 帳號密碼設定
onboarding-connect_tracker-back = 返回到 Wi-Fi 認證資訊設定
onboarding-connect_tracker-title = 連接追蹤器
onboarding-connect_tracker-description-p0 = 來到了我第二喜歡的環節,連線所有的追蹤器!
onboarding-connect_tracker-description-p1 = 只需透過 USB 連線所有尚未連線的裝置即可。
@@ -542,7 +573,7 @@ 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-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
@@ -560,9 +591,30 @@ onboarding-connect_tracker-connected_trackers =
}
onboarding-connect_tracker-next = 所有的追蹤器都連接好了
## Tracker calibration tutorial
onboarding-calibration_tutorial = IMU 校正教學
onboarding-calibration_tutorial-subtitle = 進行這項操作可以有效減少追蹤器發生飄移的機會
onboarding-calibration_tutorial-description = 每次在打開追蹤器的開關時,需要將追蹤器放置在平面一會兒來進行自動校正。您也可以透過按下“校正”按鈕來進行手動校正,<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-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
@@ -640,12 +692,26 @@ onboarding-assign_trackers-warning-WAIST =
*[unknown] 腰部已分配,但您還需要分配其它未分配的身體部位!
}
## 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
onboarding-manual_mounting-back = 返回到進入 VR
onboarding-manual_mounting = 手動配戴
onboarding-manual_mounting-description = 點選每個追蹤器並選擇它們的配戴方式
onboarding-manual_mounting-auto_mounting = 自動配戴
onboarding-manual_mounting-auto_mounting = 進行自動設定
onboarding-manual_mounting-next = 下一步
## Tracker automatic mounting setup
@@ -653,7 +719,7 @@ onboarding-manual_mounting-next = 下一步
onboarding-automatic_mounting-back = 返回到進入 VR
onboarding-automatic_mounting-title = 配戴校正
onboarding-automatic_mounting-description = 為了讓 SlimeVR 追蹤器正常運作,我們需要為你的追蹤器設定一個配戴方向,以使其與你的物理追蹤器配戴方式對齊。
onboarding-automatic_mounting-manual_mounting = 手動設定配戴方向
onboarding-automatic_mounting-manual_mounting = 進行手動設定
onboarding-automatic_mounting-next = 下一步
onboarding-automatic_mounting-prev_step = 上一步
onboarding-automatic_mounting-done-title = 配戴方向已校正。
@@ -669,12 +735,30 @@ onboarding-automatic_mounting-put_trackers_on-title = 請戴好追蹤器
onboarding-automatic_mounting-put_trackers_on-description = 為了校準配戴方向,我們將使用剛才分配的追蹤器。戴上你所有的追蹤器,你可以在右邊的圖中看到追蹤器的對應部位。
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-save = 儲存軀幹比例
onboarding-choose_proportions-file_type = 軀幹比例描述檔
## Tracker manual proportions setup
onboarding-manual_proportions-back = 返回重置教學
onboarding-manual_proportions-title = 手動調整軀幹比例
onboarding-manual_proportions-precision = 精確調整
onboarding-manual_proportions-auto = 自動校
onboarding-manual_proportions-auto = 進行自動校
onboarding-manual_proportions-ratio = 依比例分組調整
## Tracker automatic proportions setup
@@ -682,7 +766,7 @@ onboarding-manual_proportions-ratio = 依比例分組調整
onboarding-automatic_proportions-back = 返回重置教學
onboarding-automatic_proportions-title = 測量你的身體比例
onboarding-automatic_proportions-description = 為了讓 SlimeVR 追蹤器正常使用,我們需要知道你的骨頭長度。這個簡短的流程將會進行這方面的測量。
onboarding-automatic_proportions-manual = 手動校正
onboarding-automatic_proportions-manual = 進行手動校正
onboarding-automatic_proportions-prev_step = 上一步
onboarding-automatic_proportions-put_trackers_on-title = 請戴好追蹤器
onboarding-automatic_proportions-put_trackers_on-description = 為了校準你的軀幹比例,我們將使用你剛才分配的追蹤器。戴上你所有的追蹤器,你可以在右邊的圖中看到追蹤器的對應部位。
@@ -705,15 +789,15 @@ 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 = 剩餘{ $time }秒
onboarding-automatic_proportions-recording-timer = 剩餘 { $time }
onboarding-automatic_proportions-verify_results-title = 檢查結果
onboarding-automatic_proportions-verify_results-description = 檢查下面的結果,它們看起來是正確的嗎?
onboarding-automatic_proportions-verify_results-results = 錄製結果
@@ -726,3 +810,13 @@ onboarding-automatic_proportions-done-description = 你的身體比例校正已
## Home
home-no_trackers = 未偵測到或未分配追蹤器
## Status system
status_system-StatusTrackerReset = 建議執行完全重置,因為有至少一個追蹤器尚未調整
status_system-StatusSteamVRDisconnected =
{ $type ->
[steamvr_feeder] 尚未連接 SlimeVR 資料迴送程式
*[other] 尚未透過 SlimeVR 驅動程式連接到 SteamVR
}
status_system-StatusTrackerError = { $trackerName } 追蹤器發生錯誤

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

File diff suppressed because one or more lines are too long

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

@@ -23,15 +23,14 @@ custom-protocol = ["tauri/custom-protocol"]
[build-dependencies]
tauri-build = { version = "1.2", features = [] }
cfg_aliases = "0.1"
shadow-rs = "0.20"
shadow-rs = "0.23"
[dependencies]
serde_json = "1"
serde = { version = "1", features = ["derive"] }
tauri = { version = "1.2", features = ["devtools", "dialog", "fs-all", "os-all", "path-all", "shell-execute", "window-close", "window-maximize", "window-minimize", "window-set-resizable", "window-set-title", "window-start-dragging", "window-unmaximize", "window-unminimize"] }
tauri-runtime = "0.12.1"
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
pretty_env_logger = "0.4"
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"
log = "0.4"
clap = { version = "4.0.29", features = ["derive"] }
clap-verbosity-flag = "2"
@@ -39,11 +38,12 @@ rand = "0.8.5"
tempfile = "3"
which = "4.3"
glob = "0.3"
open = "3"
shadow-rs = { version = "0.20", default-features = false }
open = "4"
shadow-rs = { version = "0.23", default-features = false }
const_format = "0.2.30"
cfg-if = "1"
color-eyre = "0.6"
[target.'cfg(windows)'.dependencies]
win32job = "1"
winreg = "0.10.1"
winreg = "0.50"

View File

@@ -1,27 +1,43 @@
#![cfg_attr(all(not(debug_assertions), windows), windows_subsystem = "windows")]
use std::env;
use std::panic;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;
use std::time::Instant;
use clap::Parser;
use state::WindowState;
use tauri::api::process::{Command, CommandChild};
use tauri::Manager;
use tauri::RunEvent;
#[cfg(windows)]
use tauri::WindowEvent;
use crate::util::{
get_launch_path, show_error, valid_java_paths, Cli, JAVA_BIN, MINIMUM_JAVA_VERSION,
};
mod state;
mod util;
#[tauri::command]
fn update_window_state(
window: tauri::Window,
state: tauri::State<Mutex<WindowState>>,
) -> Result<(), String> {
let mut lock = state.lock().unwrap();
lock.update_state(&window, false)
.map_err(|e| format!("{:?}", e))?;
if window.is_maximized().map_err(|e| e.to_string())? {
window.unmaximize().map_err(|e| e.to_string())?;
lock.update_state(&window, true)
.map_err(|e| format!("{:?}", e))?;
}
Ok(())
}
fn main() {
// Make an error dialog box when panicking
panic::set_hook(Box::new(|panic_info| {
@@ -96,7 +112,7 @@ fn main() {
log::info!("Using Java binary: {:?}", java_bin);
let (recv, child) = Command::new(java_bin.to_str().unwrap())
.current_dir(p)
.args(["-Xmx512M", "-jar", "slimevr.jar", "--no-gui"])
.args(["-Xmx512M", "-jar", "slimevr.jar", "run"])
.spawn()
.expect("Unable to start the server jar");
backend = Some(child);
@@ -108,8 +124,32 @@ fn main() {
let exit_flag_terminated = exit_flag.clone();
let build_result = tauri::Builder::default()
.plugin(tauri_plugin_window_state::Builder::default().build())
.invoke_handler(tauri::generate_handler![update_window_state])
.setup(move |app| {
let window_state =
WindowState::open_state(app.path_resolver().app_config_dir().unwrap())
.unwrap_or_default();
let window = tauri::WindowBuilder::new(
app,
"local",
tauri::WindowUrl::App("index.html".into()),
)
.title("SlimeVR")
.inner_size(1289.0, 709.0)
.min_inner_size(393.0, 667.0)
.resizable(true)
.visible(true)
.decorations(false)
.fullscreen(false)
.disable_file_drop_handler()
.build()?;
if window_state.is_old() {
window_state.update_window(&window, false)?;
}
app.manage(Mutex::new(window_state));
if let Some(mut recv) = stdout_recv {
let app_handle = app.app_handle();
tauri::async_runtime::spawn(async move {
@@ -139,6 +179,12 @@ fn main() {
Ok(())
})
.on_window_event(|e| match e.event() {
WindowEvent::CloseRequested { .. } => {
let window_state = e.window().state::<Mutex<WindowState>>();
if let Err(e) = update_window_state(e.window().clone(), window_state) {
log::error!("failed to update window state {}", e)
}
}
// See https://github.com/tauri-apps/tauri/issues/4012#issuecomment-1449499149
#[cfg(windows)]
WindowEvent::Resized(_) => std::thread::sleep(std::time::Duration::from_nanos(1)),
@@ -147,8 +193,18 @@ fn main() {
.build(tauri::generate_context!());
match build_result {
Ok(app) => {
app.run(move |_app_handle, event| match event {
app.run(move |app_handle, event| match event {
RunEvent::ExitRequested { .. } => {
let window_state = app_handle.state::<Mutex<WindowState>>();
let lock = window_state.lock().unwrap();
let config_dir =
app_handle.path_resolver().app_config_dir().unwrap();
let window_state_res = lock.save_state(config_dir);
match window_state_res {
Ok(()) => log::info!("saved window state"),
Err(e) => log::error!("failed to save window state: {}", e),
}
let Some(ref mut child) = backend else { return };
let write_result = child.write(b"exit\n");
match write_result {

110
gui/src-tauri/src/state.rs Normal file
View File

@@ -0,0 +1,110 @@
use std::{fs, path::PathBuf};
use color_eyre::Result;
use serde::{Deserialize, Serialize};
use tauri::{LogicalSize, Monitor, PhysicalPosition, PhysicalSize, Window};
static STATE_FILENAME: &str = ".window-state.json";
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct WindowState {
maximized: bool,
width: f64,
height: f64,
x: i32,
y: i32,
#[serde(skip)]
old: bool,
}
impl WindowState {
pub fn open_state(path: PathBuf) -> Option<Self> {
if let Ok(file) = fs::File::open(path.join(STATE_FILENAME)) {
return serde_json::from_reader(file)
.map(|mut s: WindowState| {
s.old = true;
s
})
.ok();
}
None
}
pub fn is_old(&self) -> bool {
self.old
}
pub fn save_state(&self, path: PathBuf) -> Result<()> {
if !path.exists() {
fs::create_dir(&path)?
}
let file = fs::File::create(path.join(STATE_FILENAME))?;
serde_json::to_writer(file, self)?;
Ok(())
}
pub fn update_state(
&mut self,
window: &Window,
ignore_maximized: bool,
) -> Result<()> {
let maximized = window.is_maximized()?;
self.maximized = maximized || (self.maximized && ignore_maximized);
// We early return when it's maximized because we dont have to save the state
// of the rest of the window when it's maximized.
if maximized {
return Ok(());
}
let scale_factor = window.scale_factor()?;
let size = window.outer_size()?.to_logical::<f64>(scale_factor);
let pos = window.outer_position()?;
self.width = size.width;
self.height = size.height;
self.x = pos.x;
self.y = pos.y;
Ok(())
}
pub fn update_window(&self, window: &Window, ignore_maximized: bool) -> Result<()> {
let maximized = !ignore_maximized && window.is_maximized()?;
if maximized && !self.maximized {
window.unmaximize()?;
}
window.set_size(LogicalSize::new(self.width, self.height))?;
let pos = PhysicalPosition::new(self.x, self.y);
for monitor in window.available_monitors()? {
if monitor.contains(pos) {
window.set_position(pos)?;
break;
}
}
if !ignore_maximized && !maximized && self.maximized {
window.maximize()?;
}
Ok(())
}
}
pub trait MonitorExt {
fn contains(&self, position: PhysicalPosition<i32>) -> bool;
}
/// Allowed amount to overflow out of the screen
const ALLOWED_OVERFLOW: i32 = 16;
impl MonitorExt for Monitor {
fn contains(&self, position: PhysicalPosition<i32>) -> bool {
let PhysicalPosition { x, y } = *self.position();
let PhysicalSize { width, height } = *self.size();
(x < position.x + ALLOWED_OVERFLOW) as _
&& (position.x - ALLOWED_OVERFLOW) < (x + width as i32)
&& (y - ALLOWED_OVERFLOW) < position.y as _
&& (position.y + ALLOWED_OVERFLOW) < (y + height as i32)
}
}

View File

@@ -58,7 +58,7 @@ pub fn get_launch_path(cli: Cli) -> Option<PathBuf> {
let paths = [
cli.launch_from_path,
// AppImage passes the fakeroot in `APPDIR` env var.
env::var_os("APPDIR").map(|x| PathBuf::from(x)),
env::var_os("APPDIR").map(PathBuf::from),
env::current_dir().ok(),
// getcwd in Mac can't be trusted, so let's get the executable's path
env::current_exe()
@@ -73,10 +73,7 @@ pub fn get_launch_path(cli: Cli) -> Option<PathBuf> {
Some(PathBuf::from("/usr/share/slimevr/")),
];
paths
.into_iter()
.filter_map(|x| x)
.find(|x| is_valid_path(x))
paths.into_iter().flatten().find(|x| is_valid_path(x))
}
pub fn spawn_java(java: &OsStr, java_version: &OsStr) -> std::io::Result<Child> {

View File

@@ -34,7 +34,7 @@
}
},
"appimage": {
"bundleMediaFramework": true
"bundleMediaFramework": true
},
"macOS": {
"frameworks": [],
@@ -54,9 +54,14 @@
"active": false
},
"allowlist": {
"dialog": {
"all": false,
"save": true
},
"shell": {
"all": false,
"execute": true
"execute": true,
"open": true
},
"fs": {
"scope": ["$APP/*", "$APP"],
@@ -76,26 +81,10 @@
"minimize": true,
"unminimize": true,
"close": true,
"startDragging": true
"startDragging": true,
"setSize": true
}
},
"windows": [
{
"title": "SlimeVR",
"width": 1289,
"height": 709,
"minWidth": 880,
"minHeight": 740,
"resizable": true,
"fullscreen": false,
"decorations": false,
"transparent": false,
"fileDropEnabled": false,
"visible": true,
"hiddenTitle": true,
"tabbingIdentifier": "slimevr"
}
],
"security": {
"csp": null
}

View File

@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { createContext, useEffect, useState } from 'react';
import {
BrowserRouter as Router,
Outlet,
@@ -42,27 +42,50 @@ import { os } from '@tauri-apps/api';
import { VMCSettings } from './components/settings/pages/VMCSettings';
import { MountingChoose } from './components/onboarding/pages/mounting/MountingChoose';
import { ProportionsChoose } from './components/onboarding/pages/body-proportions/ProportionsChoose';
import { StatusProvider } from './components/providers/StatusSystemContext';
import { VersionUpdateModal } from './components/VersionUpdateModal';
import { CalibrationTutorialPage } from './components/onboarding/pages/CalibrationTutorial';
import { AssignmentTutorialPage } from './components/onboarding/pages/assignment-preparation/AssignmentTutorial';
import { open } from '@tauri-apps/api/shell';
import semver from 'semver';
import { useBreakpoint } from './hooks/breakpoint';
import { VRModePage } from './components/vr-mode/VRModePage';
export const GH_REPO = 'SlimeVR/SlimeVR-Server';
export const VersionContext = createContext('');
export const DOCS_SITE = 'https://docs.slimevr.dev/';
function Layout() {
const { loading } = useConfig();
if (loading) return <></>;
const { isMobile } = useBreakpoint('mobile');
return (
<>
<SerialDetectionModal></SerialDetectionModal>
<VersionUpdateModal></VersionUpdateModal>
<Routes>
<Route
path="/"
element={
<MainLayoutRoute>
<MainLayoutRoute isMobile={isMobile}>
<Home />
</MainLayoutRoute>
}
/>
<Route
path="/vr-mode"
element={
<MainLayoutRoute isMobile={isMobile}>
<VRModePage />
</MainLayoutRoute>
}
/>
<Route
path="/tracker/:trackernum/:deviceid"
element={
<MainLayoutRoute background={false}>
<MainLayoutRoute background={false} isMobile={isMobile}>
<TrackerSettingsPage />
</MainLayoutRoute>
}
@@ -92,6 +115,11 @@ function Layout() {
<Route path="home" element={<HomePage />} />
<Route path="wifi-creds" element={<WifiCredsPage />} />
<Route path="connect-trackers" element={<ConnectTrackersPage />} />
<Route
path="calibration-tutorial"
element={<CalibrationTutorialPage />}
/>
<Route path="assign-tutorial" element={<AssignmentTutorialPage />} />
<Route path="trackers-assign" element={<TrackersAssignPage />} />
<Route path="enter-vr" element={<EnterVRPage />} />
<Route path="mounting/choose" element={<MountingChoose />}></Route>
@@ -121,61 +149,91 @@ function Layout() {
export default function App() {
const websocketAPI = useProvideWebsocketApi();
const { l10n } = useLocalization();
const [updateFound, setUpdateFound] = useState('');
useEffect(() => {
os.type()
.then((type) => {
document.body.classList.add(type.toLowerCase());
})
.catch(console.error);
async function fetchReleases() {
const releases = await fetch(
`https://api.github.com/repos/${GH_REPO}/releases`
)
.then((res) => res.json())
.then((json: any[]) => json.filter((rl) => rl?.prerelease === false));
return () => {
os.type()
.then((type) => {
document.body.classList.remove(type.toLowerCase());
})
.catch(console.error);
};
if (
__VERSION_TAG__ &&
typeof releases[0].tag_name === 'string' &&
semver.gt(releases[0].tag_name, __VERSION_TAG__)
) {
setUpdateFound(releases[0].tag_name);
}
}
fetchReleases().catch(() => console.error('failed to fetch releases'));
}, []);
useEffect(() => {
const unlisten = listen(
'server-status',
(event: Event<[string, string]>) => {
const [eventType, s] = event.payload;
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
setTimeout(
console.log.bind(
console,
`%c[SERVER] %c${s}`,
'color:cyan',
'color:red'
)
);
} else if (eventType === 'stdout') {
setTimeout(
console.log.bind(
console,
`%c[SERVER] %c${s}`,
'color:cyan',
'color:green'
)
);
} else if (eventType === 'error') {
console.error('Error: %s', s);
} else if (eventType === 'terminated') {
console.error('Server Process Terminated: %s', s);
} else if (eventType === 'other') {
console.log('Other process event: %s', s);
if (window.__TAURI_METADATA__) {
useEffect(() => {
os.type()
.then((type) => document.body.classList.add(type.toLowerCase()))
.catch(console.error);
return () => {
os.type()
.then((type) => document.body.classList.remove(type.toLowerCase()))
.catch(console.error);
};
}, []);
}
if (window.__TAURI_METADATA__) {
useEffect(() => {
const unlisten = listen(
'server-status',
(event: Event<[string, string]>) => {
const [eventType, s] = event.payload;
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
setTimeout(
console.log.bind(
console,
`%c[SERVER] %c${s}`,
'color:cyan',
'color:red'
)
);
} else if (eventType === 'stdout') {
setTimeout(
console.log.bind(
console,
`%c[SERVER] %c${s}`,
'color:cyan',
'color:green'
)
);
} else if (eventType === 'error') {
console.error('Error: %s', s);
} else if (eventType === 'terminated') {
console.error('Server Process Terminated: %s', s);
} else if (eventType === 'other') {
console.log('Other process event: %s', s);
}
}
);
return () => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
unlisten.then(() => {});
};
}, []);
}
useEffect(() => {
function onKeyboard(ev: KeyboardEvent) {
if (ev.key === 'F1') {
return open(DOCS_SITE).catch(() => window.open(DOCS_SITE, '_blank'));
}
);
return () => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
unlisten.then(() => {});
};
}
document.addEventListener('keyup', onKeyboard);
return () => document.removeEventListener('keyup', onKeyboard);
}, []);
return (
@@ -184,21 +242,25 @@ export default function App() {
<WebSocketApiContext.Provider value={websocketAPI}>
<AppContextProvider>
<OnboardingContextProvider>
<div className="h-full w-full text-standard bg-background-80 text-background-10">
<div className="flex-col h-full">
{!websocketAPI.isConnected && (
<>
<TopBar></TopBar>
<div className="flex w-full h-full justify-center items-center p-2">
{websocketAPI.isFirstConnection
? l10n.getString('websocket-connecting')
: l10n.getString('websocket-connection_lost')}
</div>
</>
)}
{websocketAPI.isConnected && <Layout></Layout>}
</div>
</div>
<StatusProvider>
<VersionContext.Provider value={updateFound}>
<div className="h-full w-full text-standard bg-background-80 text-background-10">
<div className="flex-col h-full">
{!websocketAPI.isConnected && (
<>
<TopBar></TopBar>
<div className="flex w-full h-full justify-center items-center p-2">
{websocketAPI.isFirstConnection
? l10n.getString('websocket-connecting')
: l10n.getString('websocket-connection_lost')}
</div>
</>
)}
{websocketAPI.isConnected && <Layout></Layout>}
</div>
</div>
</VersionContext.Provider>
</StatusProvider>
</OnboardingContextProvider>
</AppContextProvider>
</WebSocketApiContext.Provider>

View File

@@ -3,48 +3,36 @@ import { ReactNode, useEffect, useState } from 'react';
import {
LegTweaksTmpChangeT,
LegTweaksTmpClearT,
ResetType,
RpcMessage,
SettingsRequestT,
SettingsResponseT,
} from 'solarxr-protocol';
import { useConfig } from '../hooks/config';
import { useLayout } from '../hooks/layout';
import { BVHButton } from './BVHButton';
import { ResetButton } from './home/ResetButton';
import { useElemSize, useLayout } from '../hooks/layout';
import { Navbar } from './Navbar';
import { TopBar } from './TopBar';
import { DeveloperModeWidget } from './widgets/DeveloperModeWidget';
import { OverlayWidget } from './widgets/OverlayWidget';
import { ClearDriftCompensationButton } from './ClearDriftCompensationButton';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { WidgetsComponent } from './WidgetsComponent';
export function MainLayoutRoute({
children,
background = true,
widgets = true,
isMobile = undefined,
}: {
children: ReactNode;
background?: boolean;
isMobile?: boolean;
widgets?: boolean;
}) {
const { height, ref: navRef } = useElemSize<HTMLDivElement>();
const { layoutHeight, ref } = useLayout<HTMLDivElement>();
const { layoutWidth, ref: refw } = useLayout<HTMLDivElement>();
const { config } = useConfig();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [driftCompensationEnabled, setDriftCompensationEnabled] =
useState(false);
const { sendRPCPacket } = useWebsocketAPI();
const [ProportionsLastPageOpen, setProportionsLastPageOpen] = useState(true);
useEffect(() => {
sendRPCPacket(RpcMessage.SettingsRequest, new SettingsRequestT());
}, []);
useRPCPacket(RpcMessage.SettingsResponse, (settings: SettingsResponseT) => {
if (settings.driftCompensation != null)
setDriftCompensationEnabled(settings.driftCompensation.enabled);
});
function usePageChanged(callback: () => void) {
useEffect(() => {
callback();
@@ -75,53 +63,34 @@ export function MainLayoutRoute({
return (
<>
<TopBar></TopBar>
<div ref={ref} className="flex-grow" style={{ height: layoutHeight }}>
<div className="flex h-full pb-3">
<Navbar></Navbar>
<div
ref={ref}
className="flex-grow"
style={{ height: layoutHeight - height }}
>
<div className="flex h-full xs:pb-3">
{!isMobile && <Navbar></Navbar>}
<div
className="flex gap-2 pr-3 w-full"
className="flex gap-2 xs:pr-3 w-full"
ref={refw}
style={{ minWidth: layoutWidth }}
>
<div
className={classNames(
'flex flex-col rounded-xl w-full overflow-hidden',
'flex flex-col rounded-xl w-full overflow-hidden mobile:overflow-y-auto',
background && 'bg-background-70'
)}
>
{children}
</div>
{widgets && (
{!isMobile && widgets && (
<div className="flex flex-col px-2 min-w-[274px] w-[274px] gap-2 pt-2 rounded-xl overflow-y-auto bg-background-70">
<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>
)}
<BVHButton></BVHButton>
{driftCompensationEnabled && (
<ClearDriftCompensationButton></ClearDriftCompensationButton>
)}
</div>
<div className="w-full">
<OverlayWidget></OverlayWidget>
</div>
{config?.debug && (
<div className="w-full">
<DeveloperModeWidget></DeveloperModeWidget>
</div>
)}
<WidgetsComponent></WidgetsComponent>
</div>
)}
</div>
</div>
<div ref={navRef}>{isMobile && <Navbar></Navbar>}</div>
</div>
</>
);

View File

@@ -2,13 +2,13 @@ import { useLocalization } from '@fluent/react';
import classnames from 'classnames';
import { ReactNode } from 'react';
import { NavLink, useMatch } from 'react-router-dom';
import { useBodyProportions } from '../hooks/body-proportions';
import { CubeIcon } from './commons/icon/CubeIcon';
import { GearIcon } from './commons/icon/GearIcon';
import { HumanIcon } from './commons/icon/HumanIcon';
import { RulerIcon } from './commons/icon/RulerIcon';
import { SparkleIcon } from './commons/icon/SparkleIcon';
import { WrenchIcon } from './commons/icon/WrenchIcons';
import { useBreakpoint } from '../hooks/breakpoint';
export function NavButton({
to,
@@ -32,7 +32,9 @@ export function NavButton({
to={to}
state={state}
className={classnames(
'flex flex-col justify-center gap-4 w-[85px] py-3 rounded-md group select-text',
'flex flex-col justify-center xs:gap-4 mobile:gap-2',
'xs:w-[85px] mobile:w-[80px] mobile:h-[80px]',
'xs:py-3 mobile:py-4 rounded-md mobile:rounded-b-none group select-text',
{
'bg-accent-background-50 fill-accent-background-20': doesMatch,
'hover:bg-background-70': !doesMatch,
@@ -61,42 +63,56 @@ export function NavButton({
);
}
export function Navbar() {
export function MainLinks() {
const { l10n } = useLocalization();
const { lastUsedPage } = useBodyProportions();
return (
<>
<NavButton to="/" icon={<CubeIcon></CubeIcon>}>
{l10n.getString('navbar-home')}
</NavButton>
<NavButton
to="/onboarding/trackers-assign"
state={{ alonePage: true }}
icon={<HumanIcon></HumanIcon>}
>
{l10n.getString('navbar-trackers_assign')}
</NavButton>
<NavButton
to="/onboarding/mounting/choose"
match="/onboarding/mounting/*"
state={{ alonePage: true }}
icon={<WrenchIcon></WrenchIcon>}
>
{l10n.getString('navbar-mounting')}
</NavButton>
<NavButton
to="/onboarding/body-proportions/choose"
match="/onboarding/body-proportions/*"
state={{ alonePage: true }}
icon={<RulerIcon></RulerIcon>}
>
{l10n.getString('navbar-body_proportions')}
</NavButton>
<NavButton to="/onboarding/home" icon={<SparkleIcon></SparkleIcon>}>
{l10n.getString('navbar-onboarding')}
</NavButton>
</>
);
}
export function Navbar() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
return isMobile ? (
<div className="flex flex-row justify-around px-2 pt-2 bg-background-80 gap-2">
<MainLinks></MainLinks>
</div>
) : (
<div className="flex flex-col px-2 pt-2">
<div className="flex flex-col flex-grow gap-2">
<NavButton to="/" icon={<CubeIcon></CubeIcon>}>
{l10n.getString('navbar-home')}
</NavButton>
<NavButton
to="/onboarding/trackers-assign"
state={{ alonePage: true }}
icon={<HumanIcon></HumanIcon>}
>
{l10n.getString('navbar-trackers_assign')}
</NavButton>
<NavButton
to="/onboarding/mounting/choose"
match="/onboarding/mounting/*"
state={{ alonePage: true }}
icon={<WrenchIcon></WrenchIcon>}
>
{l10n.getString('navbar-mounting')}
</NavButton>
<NavButton
to={lastUsedPage}
match="/onboarding/body-proportions/*"
state={{ alonePage: true }}
icon={<RulerIcon></RulerIcon>}
>
{l10n.getString('navbar-body_proportions')}
</NavButton>
<NavButton to="/onboarding/home" icon={<SparkleIcon></SparkleIcon>}>
{l10n.getString('navbar-onboarding')}
</NavButton>
<MainLinks></MainLinks>
</div>
<NavButton
to="/settings/trackers"

View File

@@ -25,8 +25,7 @@ export function SerialDetectionModal() {
const [isOpen, setOpen] = useState<SerialDeviceT | null>(null);
const [showWifiForm, setShowWifiForm] = useState(false);
const { handleSubmit, submitWifiCreds, formState, hasWifiCreds, control } =
useWifiForm();
const { handleSubmit, submitWifiCreds, formState, control } = useWifiForm();
const closeModal = () => {
setOpen(null);
@@ -39,12 +38,13 @@ export function SerialDetectionModal() {
};
const openWifi = () => {
if (!hasWifiCreds) {
setShowWifiForm(true);
} else {
closeModal();
nav('/onboarding/connect-trackers', { state: { alonePage: true } });
}
setShowWifiForm(true);
// if (!hasWifiCreds) {
// setShowWifiForm(true);
// } else {
// closeModal();
// nav('/onboarding/connect-trackers', { state: { alonePage: true } });
// }
};
const modalWifiSubmit = (form: WifiFormData) => {
@@ -88,10 +88,10 @@ export function SerialDetectionModal() {
<Button variant="primary" onClick={openWifi}>
{l10n.getString('serial_detection-open_wifi')}
</Button>
<Button variant="tiertiary" onClick={openSerial}>
<Button variant="tertiary" onClick={openSerial}>
{l10n.getString('serial_detection-open_serial')}
</Button>
<Button variant="secondary" onClick={closeModal}>
<Button variant="tertiary" onClick={closeModal}>
{l10n.getString('serial_detection-close')}
</Button>
</>
@@ -102,7 +102,9 @@ export function SerialDetectionModal() {
className="flex flex-col gap-3"
>
<div className="flex flex-col items-center gap-3">
<BulbIcon></BulbIcon>
<div className="fill-background-10">
<BulbIcon></BulbIcon>
</div>
<Typography variant="main-title">
{l10n.getString('serial_detection-new_device-p0')}
</Typography>
@@ -147,7 +149,7 @@ export function SerialDetectionModal() {
>
{l10n.getString('serial_detection-submit')}
</Button>
<Button variant="secondary" onClick={closeModal}>
<Button variant="tertiary" onClick={closeModal}>
{l10n.getString('serial_detection-close')}
</Button>
</form>

View File

@@ -1,5 +1,5 @@
import { appWindow } from '@tauri-apps/api/window';
import { ReactNode, useEffect, useState } from 'react';
import { ReactNode, useContext, useEffect, useState } from 'react';
import { NavLink, useMatch } from 'react-router-dom';
import {
RpcMessage,
@@ -13,6 +13,32 @@ import { MinimiseIcon } from './commons/icon/MinimiseIcon';
import { SlimeVRIcon } from './commons/icon/SimevrIcon';
import { ProgressBar } from './commons/ProgressBar';
import { Typography } from './commons/Typography';
import { DownloadIcon } from './commons/icon/DownloadIcon';
import { open } from '@tauri-apps/api/shell';
import { GH_REPO, VersionContext, DOCS_SITE } from '../App';
import classNames from 'classnames';
import { QuestionIcon } from './commons/icon/QuestionIcon';
import { useBreakpoint, useIsTauri } from '../hooks/breakpoint';
import { GearIcon } from './commons/icon/GearIcon';
import { invoke } from '@tauri-apps/api';
export function VersionTag() {
return (
<div
className={classNames(
'flex justify-around flex-col text-standard-bold',
'text-status-success bg-status-success bg-opacity-20 rounded-lg',
'px-3 select-text cursor-pointer'
)}
onClick={() => {
const url = `https://github.com/${GH_REPO}/releases`;
open(url).catch(() => window.open(url, '_blank'));
}}
>
{(__VERSION_TAG__ || __COMMIT_HASH__) + (__GIT_CLEAN__ ? '' : '-dirty')}
</div>
);
}
export function TopBar({
progress,
@@ -20,7 +46,10 @@ export function TopBar({
children?: ReactNode;
progress?: number;
}) {
const isTauri = useIsTauri();
const { isMobile } = useBreakpoint('mobile');
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const version = useContext(VersionContext);
const [localIp, setLocalIp] = useState<string | null>(null);
const doesMatchSettings = useMatch({
path: '/settings/*',
@@ -38,69 +67,153 @@ export function TopBar({
);
return (
<div data-tauri-drag-region className="flex gap-2 h-[38px] z-50">
<div
className="flex px-2 pb-1 mt-3 justify-around z-50"
data-tauri-drag-region
>
<div className="flex gap-2" data-tauri-drag-region>
<NavLink
to="/"
className="flex justify-around flex-col select-all"
<>
<div className="flex gap-0 flex-col">
<div className="h-[3px]"></div>
<div data-tauri-drag-region className="flex gap-2 h-[38px] z-50">
<div
className="flex px-2 pb-1 mt-3 justify-around z-50"
data-tauri-drag-region
>
<SlimeVRIcon></SlimeVRIcon>
</NavLink>
<div className="flex justify-around flex-col" data-tauri-drag-region>
<Typography>SlimeVR</Typography>
</div>
<div className="flex justify-around flex-col text-standard-bold text-status-success bg-status-success bg-opacity-20 rounded-lg px-3 select-text">
{(__VERSION_TAG__ || __COMMIT_HASH__) +
(__GIT_CLEAN__ ? '' : '-dirty')}
</div>
{doesMatchSettings && (
<div className="flex justify-around flex-col text-standard-bold text-status-special bg-status-special bg-opacity-20 rounded-lg px-3 select-text">
{localIp || 'unknown local ip'}
<div className="flex gap-2 mobile:w-5" data-tauri-drag-region>
<NavLink
to="/"
className="flex justify-around flex-col select-all"
data-tauri-drag-region
>
<SlimeVRIcon></SlimeVRIcon>
</NavLink>
{(isTauri || !isMobile) && (
<div
className={classNames('flex justify-around flex-col')}
data-tauri-drag-region
>
<Typography>SlimeVR</Typography>
</div>
)}
{!isMobile && (
<>
<VersionTag></VersionTag>
{doesMatchSettings && (
<div
className={classNames(
'flex justify-around flex-col text-standard-bold text-status-special',
'bg-status-special bg-opacity-20 rounded-lg px-3 select-text'
)}
>
{localIp || 'unknown local ip'}
</div>
)}
</>
)}
{version && (
<div
className="cursor-pointer"
onClick={() => {
const url = document.body.classList.contains('windows_nt')
? 'https://slimevr.dev/download'
: `https://github.com/${GH_REPO}/releases/latest`;
open(url).catch(() => window.open(url, '_blank'));
}}
>
<DownloadIcon></DownloadIcon>
</div>
)}
</div>
)}
</div>
<div
className="flex flex-grow items-center h-full justify-center z-50"
data-tauri-drag-region
>
{!isMobile && (
<>
<div
className="flex max-w-xl h-full items-center w-full"
data-tauri-drag-region
>
{progress !== undefined && (
<ProgressBar
progress={progress}
height={3}
parts={3}
></ProgressBar>
)}
</div>
</>
)}
{!isTauri && (
<div className="flex flex-row gap-2">
<div
className="flex justify-around flex-col xs:hidden"
data-tauri-drag-region
>
<Typography variant="section-title">SlimeVR</Typography>
</div>
</div>
)}
</div>
<div
className="flex justify-end items-center px-2 gap-2 z-50"
data-tauri-drag-region
>
<NavLink
to="/settings/trackers"
className="flex justify-around flex-col select-all fill-background-50"
data-tauri-drag-region
state={{ scrollTo: 'steamvr' }}
>
<GearIcon></GearIcon>
</NavLink>
{!isMobile && (
<div
className={classNames(
'flex items-center justify-center stroke-window-icon',
'hover:bg-background-60 rounded-full w-7 h-7 cursor-pointer'
)}
onClick={() =>
open(DOCS_SITE).catch(() => window.open(DOCS_SITE, '_blank'))
}
>
<QuestionIcon></QuestionIcon>
</div>
)}
{isTauri && (
<>
<div
className="flex items-center justify-center hover:bg-background-60 rounded-full w-7 h-7"
onClick={() => appWindow.minimize()}
>
<MinimiseIcon></MinimiseIcon>
</div>
<div
className="flex items-center justify-center hover:bg-background-60 rounded-full w-7 h-7"
onClick={() => appWindow.toggleMaximize()}
>
<MaximiseIcon></MaximiseIcon>
</div>
<div
className="flex items-center justify-center hover:bg-background-60 rounded-full w-7 h-7"
onClick={async () => {
await invoke('update_window_state');
appWindow.close();
}}
>
<CloseIcon></CloseIcon>
</div>
</>
)}
</div>
</div>
</div>
<div
className="flex flex-grow items-center h-full justify-center z-50"
data-tauri-drag-region
>
<div
className="flex max-w-xl h-full items-center w-full"
data-tauri-drag-region
>
{progress !== undefined && (
{isMobile && progress !== undefined && (
<div className="flex gap-2 px-2 h-6 mb-2 justify-center flex-col border-b border-accent-background-30">
<ProgressBar progress={progress} height={3} parts={3}></ProgressBar>
)}
</div>
</div>
)}
</div>
<div
className="flex justify-end items-center px-2 gap-2 z-50"
data-tauri-drag-region
>
<div
className="flex items-center justify-center hover:bg-background-60 rounded-full w-7 h-7"
onClick={() => appWindow.minimize()}
>
<MinimiseIcon></MinimiseIcon>
</div>
<div
className="flex items-center justify-center hover:bg-background-60 rounded-full w-7 h-7"
onClick={() => appWindow.toggleMaximize()}
>
<MaximiseIcon></MaximiseIcon>
</div>
<div
className="flex items-center justify-center hover:bg-background-60 rounded-full w-7 h-7"
onClick={() => appWindow.close()}
>
<CloseIcon></CloseIcon>
</div>
</div>
</div>
</>
);
}

View File

@@ -0,0 +1,33 @@
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { SetPauseTrackingRequestT, RpcMessage } from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { PlayIcon } from './commons/icon/PlayIcon';
import { PauseIcon } from './commons/icon/PauseIcon';
export function TrackingPauseButton(
props: React.HTMLAttributes<HTMLButtonElement>
) {
const { l10n } = useLocalization();
const { sendRPCPacket } = useWebsocketAPI();
const [trackingPause, setTrackingPause] = useState(false);
const toggleTracking = () => {
const pause = new SetPauseTrackingRequestT();
pause.pauseTracking = !trackingPause;
setTrackingPause(pause.pauseTracking);
sendRPCPacket(RpcMessage.SetPauseTrackingRequest, pause);
};
return (
<BigButton
text={l10n.getString(
trackingPause ? 'tracking-paused' : 'tracking-unpaused'
)}
icon={trackingPause ? <PlayIcon width={20} /> : <PauseIcon width={20} />}
onClick={toggleTracking}
className={props.className}
></BigButton>
);
}

View File

@@ -0,0 +1,206 @@
import { useLocalization } from '@fluent/react';
import { useContext, useState } from 'react';
import { BaseModal } from './commons/BaseModal';
import { Button } from './commons/Button';
import { Typography } from './commons/Typography';
import { open } from '@tauri-apps/api/shell';
import semver from 'semver';
import { GH_REPO, VersionContext } from '../App';
export function VersionUpdateModal() {
const { l10n } = useLocalization();
const newVersion = useContext(VersionContext);
const [forceClose, setForceClose] = useState(false);
const closeModal = () => {
localStorage.setItem('lastVersionFound', newVersion);
setForceClose(true);
};
let isVersionNew = false;
try {
if (newVersion) {
isVersionNew = semver.gt(
newVersion,
localStorage.getItem('lastVersionFound') || 'v0.0.0'
);
}
} catch {
console.error('failed to parse new version');
}
return (
<BaseModal
isOpen={!forceClose && !!newVersion && isVersionNew}
onRequestClose={closeModal}
>
<div className="flex flex-col gap-3">
<>
<div className="flex flex-col items-center gap-3 fill-accent-background-20">
<div className="flex flex-col items-center gap-2">
<Typography variant="main-title">
{l10n.getString('version_update-title', {
version: newVersion,
})}
</Typography>
<Typography variant="standard">
{l10n.getString('version_update-description')}
</Typography>
</div>
</div>
<Button
variant="primary"
onClick={async () => {
const url = document.body.classList.contains('windows_nt')
? 'https://slimevr.dev/download'
: `https://github.com/${GH_REPO}/releases/latest`;
await open(url).catch(() => window.open(url, '_blank'));
closeModal();
}}
>
{l10n.getString('version_update-update')}
</Button>
<Button variant="tertiary" onClick={closeModal}>
{l10n.getString('version_update-close')}
</Button>
</>
</div>
</BaseModal>
);
}
/**
* A GitHub release.
*/
export interface Release {
url: string;
html_url: string;
assets_url: string;
upload_url: string;
tarball_url: string | null;
zipball_url: string | null;
id: number;
node_id: string;
/**
* The name of the tag.
*/
tag_name: string;
/**
* Specifies the commitish value that determines where the Git tag is created from.
*/
target_commitish: string;
name: string | null;
body?: string | null;
/**
* true to create a draft (unpublished) release, false to create a published one.
*/
draft: boolean;
/**
* Whether to identify the release as a prerelease or a full release.
*/
prerelease: boolean;
created_at: string;
published_at: string | null;
author: SimpleUser;
assets: ReleaseAsset[];
body_html?: string;
body_text?: string;
mentions_count?: number;
/**
* The URL of the release discussion.
*/
discussion_url?: string;
reactions?: ReactionRollup;
[k: string]: unknown;
}
/**
* A GitHub user.
*/
export interface SimpleUser {
name?: string | null;
email?: string | null;
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string | null;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
starred_at?: string;
[k: string]: unknown;
}
/**
* Data related to a release.
*/
export interface ReleaseAsset {
url: string;
browser_download_url: string;
id: number;
node_id: string;
/**
* The file name of the asset.
*/
name: string;
label: string | null;
/**
* State of the release asset.
*/
state: 'uploaded' | 'open';
content_type: string;
size: number;
download_count: number;
created_at: string;
updated_at: string;
uploader: null | SimpleUser1;
[k: string]: unknown;
}
/**
* A GitHub user.
*/
export interface SimpleUser1 {
name?: string | null;
email?: string | null;
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string | null;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
starred_at?: string;
[k: string]: unknown;
}
export interface ReactionRollup {
url: string;
total_count: number;
'+1': number;
'-1': number;
laugh: number;
confused: number;
heart: number;
hooray: number;
eyes: number;
rocket: number;
[k: string]: unknown;
}

View File

@@ -0,0 +1,76 @@
import { Localized, useLocalization } from '@fluent/react';
import { BVHButton } from './BVHButton';
import { ClearDriftCompensationButton } from './ClearDriftCompensationButton';
import { TrackingPauseButton } from './TrackingPauseButton';
import { ResetButton } from './home/ResetButton';
import { OverlayWidget } from './widgets/OverlayWidget';
import { TipBox } from './commons/TipBox';
import { DeveloperModeWidget } from './widgets/DeveloperModeWidget';
import { useConfig } from '../hooks/config';
import {
ResetType,
RpcMessage,
SettingsResponseT,
StatusData,
} from 'solarxr-protocol';
import { useMemo, useState } from 'react';
import { parseStatusToLocale, useStatusContext } from '../hooks/status-system';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useAppContext } from '../hooks/app';
export function WidgetsComponent() {
const { config } = useConfig();
const { useRPCPacket } = useWebsocketAPI();
const [driftCompensationEnabled, setDriftCompensationEnabled] =
useState(false);
const { trackers } = useAppContext();
const { statuses } = useStatusContext();
const { l10n } = useLocalization();
const unprioritizedStatuses = useMemo(
() => Object.values(statuses).filter((status) => !status.prioritized),
[statuses]
);
useRPCPacket(RpcMessage.SettingsResponse, (settings: SettingsResponseT) => {
if (settings.driftCompensation != null)
setDriftCompensationEnabled(settings.driftCompensation.enabled);
});
return (
<>
<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>
)}
<BVHButton></BVHButton>
<TrackingPauseButton></TrackingPauseButton>
{driftCompensationEnabled && (
<ClearDriftCompensationButton></ClearDriftCompensationButton>
)}
</div>
<div className="w-full">
<OverlayWidget></OverlayWidget>
</div>
<div className="w-full flex flex-col max-h-[33%] gap-3 overflow-y-auto mb-2">
{unprioritizedStatuses.map((status) => (
<Localized
id={`status_system-${StatusData[status.dataType]}`}
vars={parseStatusToLocale(status, trackers, l10n)}
key={status.id}
>
<TipBox whitespace={false} hideIcon={true}>
{`Warning, you should fix ${StatusData[status.dataType]}`}
</TipBox>
</Localized>
))}
</div>
{config?.debug && (
<div className="w-full">
<DeveloperModeWidget></DeveloperModeWidget>
</div>
)}
</>
);
}

View File

@@ -25,7 +25,7 @@ export function BaseModal({
props.className ||
classNames(
'items-center focus:ring-transparent focus:ring-offset-transparent',
'focus:outline-transparent outline-none bg-background-60 p-6 rounded-lg',
'focus:outline-transparent outline-none bg-background-60 p-6 rounded-lg m-2',
'text-background-10'
)
}

View File

@@ -2,6 +2,7 @@ import classNames from 'classnames';
import { ReactNode, useLayoutEffect, useRef, useState } from 'react';
import { BodyPart } from 'solarxr-protocol';
import { PersonFrontIcon } from './PersonFrontIcon';
import { useBreakpoint } from '../../hooks/breakpoint';
export function BodyInteractions({
leftControls,
@@ -22,6 +23,8 @@ export function BodyInteractions({
onSelectRole: (role: BodyPart) => void;
highlightedRoles: BodyPart[];
}) {
const { isMobile } = useBreakpoint('mobile');
const personRef = useRef<HTMLDivElement | null>(null);
const leftContainerRef = useRef<HTMLDivElement | null>(null);
const rightContainerRef = useRef<HTMLDivElement | null>(null);
@@ -123,7 +126,7 @@ export function BodyInteractions({
controlPosition.left < slot.left ? controlPosition.width : 0;
const constolLeft = controlPosition.left + offsetX;
const LINE_BREAK_WIDTH = 40;
const LINE_BREAK_WIDTH = isMobile ? 20 : 40;
const leftOffsetX =
LINE_BREAK_WIDTH * (controlPosition.left < slot.left ? -1 : 1);
@@ -160,7 +163,7 @@ export function BodyInteractions({
ref={personRef}
className={classNames(
'relative w-full flex justify-center',
variant === 'tracker-select' && 'mx-10'
variant === 'tracker-select' && 'mobile:mx-0 xs:mx-10'
)}
>
<PersonFrontIcon width={width}></PersonFrontIcon>

View File

@@ -33,7 +33,7 @@ export const mapPart: Record<
currentLocales.includes('en-x-owo') ? (
<PawIcon></PawIcon>
) : (
<FootIcon width={width} flipped></FootIcon>
<FootIcon width={width}></FootIcon>
),
[BodyPart.LEFT_HAND]: ({ width }) => (
<ControllerIcon width={width}></ControllerIcon>

View File

@@ -49,7 +49,7 @@ export function Button({
}: {
children: ReactNode;
icon?: ReactNode;
variant: 'primary' | 'secondary' | 'tiertiary' | 'quaternary';
variant: 'primary' | 'secondary' | 'tertiary' | 'quaternary';
to?: string;
loading?: boolean;
rounded?: boolean;
@@ -69,7 +69,7 @@ export function Button({
'bg-background-60 hover:bg-background-60 cursor-not-allowed text-background-40':
disabled,
}),
tiertiary: classNames({
tertiary: classNames({
'bg-background-50 hover:bg-background-40 text-standard text-background-10':
!disabled,
'bg-background-50 hover:bg-background-50 cursor-not-allowed text-background-40':

View File

@@ -14,14 +14,16 @@ export function Dropdown({
direction = 'up',
variant = 'primary',
alignment = 'right',
display = 'fit',
placeholder,
control,
name,
items = [],
}: {
direction?: DropdownDirection;
variant?: 'primary' | 'secondary';
variant?: 'primary' | 'secondary' | 'tertiary';
alignment?: 'right' | 'left';
display?: 'fit' | 'block';
placeholder: string;
control: Control<any>;
name: string;
@@ -37,10 +39,39 @@ export function Dropdown({
}
}
document.addEventListener('wheel', onWheelEvent, { passive: true });
function onTouchEvent(event: TouchEvent) {
// Check if we touch scroll outside of the dropdown
if (
isOpen &&
!document
.querySelector('div.dropdown-scroll')
?.contains(event.target as HTMLDivElement)
) {
setOpen(false);
}
}
function onClick(event: MouseEvent) {
const isInDropdownScroll = document
.querySelector('div.dropdown-scroll')
?.contains(event.target as HTMLDivElement);
const isInDropdown = document
.querySelector('div.dropdown')
?.contains(event.target as HTMLDivElement);
if (isOpen && !isInDropdownScroll && !isInDropdown) {
setOpen(false);
}
}
document.addEventListener('click', onClick, false);
document.addEventListener('touchmove', onTouchEvent, false);
// TS doesn't let me specify { passive: true }, but I believe it will work anyways
return () => document.removeEventListener('wheel', onWheelEvent);
document.addEventListener('wheel', onWheelEvent, { passive: true });
return () => {
document.removeEventListener('wheel', onWheelEvent);
document.removeEventListener('click', onClick);
document.removeEventListener('touchmove', onTouchEvent);
};
}, [isOpen]);
return (
@@ -55,15 +86,23 @@ export function Dropdown({
onClick={() => setOpen(false)}
></div>
)}
<div className="relative w-fit">
<div
className={classNames(
'relative',
display === 'fit' && 'w-fit',
display === 'block' && 'w-full'
)}
>
<div
className={classNames(
'min-h-[35px] text-background-10 px-5 py-2.5 rounded-md focus:ring-4 text-center',
'min-h-[35px] text-background-10 px-5 py-2.5 rounded-md focus:ring-4 text-center dropdown',
'flex cursor-pointer',
variant == 'primary' &&
'bg-background-60 hover:bg-background-50',
variant == 'secondary' &&
'bg-background-70 hover:bg-background-60'
'bg-background-70 hover:bg-background-60',
variant == 'tertiary' &&
'bg-accent-background-30 hover:bg-accent-background-20'
)}
onClick={() => setOpen((open) => !open)}
onKeyDown={(ev) => a11yClick(ev) && setOpen((open) => !open)}
@@ -101,21 +140,32 @@ export function Dropdown({
className={classNames(
'absolute z-10 rounded shadow min-w-max max-h-[50vh]',
'overflow-y-auto dropdown-scroll',
display === 'fit' && 'w-fit',
display === 'block' && 'w-full',
direction === 'up' && 'bottom-[45px]',
direction === 'down' && 'top-[45px]',
variant == 'primary' && 'bg-background-60',
variant == 'secondary' && 'bg-background-70',
variant == 'tertiary' && 'bg-accent-background-30',
alignment === 'right' && 'right-0',
alignment === 'left' && 'left-0'
)}
>
<ul className="py-1 text-sm text-background-20 flex flex-col pr-2">
<ul className="py-1 text-sm flex flex-col ">
{items.map((item) => (
<li
className={classNames(
'py-2 px-4 hover:text-background-10 min-w-max cursor-pointer',
variant == 'primary' && 'hover:bg-background-50',
variant == 'secondary' && 'hover:bg-background-60'
'py-2 px-4 min-w-max cursor-pointer pr-2',
variant == 'primary' &&
'hover:bg-background-50 text-background-20 hover:text-background-10',
variant == 'secondary' &&
'hover:bg-background-60 text-background-20 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'
)}
onClick={() => {
onChange(item.value);

View File

@@ -4,7 +4,7 @@ import { Control, Controller, UseControllerProps } from 'react-hook-form';
import { EyeIcon } from './icon/EyeIcon';
interface InputProps {
variant?: 'primary' | 'secondary';
variant?: 'primary' | 'secondary' | 'tertiary';
label?: string;
name: string;
}
@@ -12,7 +12,7 @@ interface InputProps {
export const InputInside = forwardRef<
HTMLInputElement,
{
variant?: 'primary' | 'secondary';
variant?: 'primary' | 'secondary' | 'tertiary';
label?: string;
onChange: () => void;
} & Partial<HTMLInputElement>
@@ -40,11 +40,12 @@ export const InputInside = forwardRef<
const variantsMap = {
primary: classNames('bg-background-60 border-background-60'),
secondary: classNames('bg-background-50 border-background-50'),
tertiary: classNames('bg-background-40 border-background-40'),
};
return classNames(
variantsMap[variant],
'w-full focus:ring-transparent focus:ring-offset-transparent focus:outline-transparent rounded-md bg-background-60 border-background-60 focus:border-accent-background-40 placeholder:text-background-30 text-standard relative'
'w-full focus:ring-transparent focus:ring-offset-transparent focus:outline-transparent rounded-md focus:border-accent-background-40 placeholder:text-background-30 text-standard relative'
);
}, [variant]);

View File

@@ -35,7 +35,7 @@ export function NumberSelector({
<div className="flex gap-2 bg-background-60 p-2 rounded-lg">
<div className="flex">
<Button
variant="tiertiary"
variant="tertiary"
rounded
onClick={() => onChange(stepFn(value, false))}
disabled={stepFn(value, false) < min}
@@ -48,7 +48,7 @@ export function NumberSelector({
</div>
<div className="flex">
<Button
variant="tiertiary"
variant="tertiary"
rounded
onClick={() => onChange(stepFn(value, true))}
disabled={stepFn(value, true) > max}

View File

@@ -2,15 +2,34 @@ import { ReactNode } from 'react';
import { BulbIcon } from './icon/BulbIcon';
import { WarningIcon } from './icon/WarningIcon';
import { Typography } from './Typography';
import classNames from 'classnames';
export function TipBox({ children }: { children: ReactNode }) {
export function TipBox({
children,
hideIcon = false,
whitespace = false,
}: {
children: ReactNode;
hideIcon?: boolean;
whitespace?: boolean;
}) {
return (
<div className="flex flex-row gap-4 bg-accent-background-50 p-4 rounded-md">
<div className="fill-accent-background-20 flex flex-col justify-center">
<div
className={classNames(
'fill-accent-background-20 flex flex-col justify-center',
hideIcon && 'hidden'
)}
>
<BulbIcon></BulbIcon>
</div>
<div className="flex flex-col">
<Typography color="text-accent-background-10">{children}</Typography>
<Typography
color="text-accent-background-10"
whitespace={whitespace ? 'whitespace-pre' : undefined}
>
{children}
</Typography>
</div>
</div>
);
@@ -19,14 +38,30 @@ export function TipBox({ children }: { children: ReactNode }) {
/**
* Will respect new lines and spacing given in text
*/
export function WarningBox({ children }: { children: ReactNode }) {
export function WarningBox({
children,
whitespace = true,
hideIcon = false,
}: {
children: ReactNode;
whitespace?: boolean;
hideIcon?: boolean;
}) {
return (
<div className="flex flex-row gap-4 bg-status-warning p-4 rounded-md">
<div className="text-background-60 flex flex-col justify-center">
<div
className={classNames(
'text-background-60 flex flex-col justify-center',
hideIcon && 'hidden'
)}
>
<WarningIcon></WarningIcon>
</div>
<div className="flex flex-col">
<Typography color="text-background-60" whitespace="whitespace-pre">
<Typography
color="text-background-60"
whitespace={whitespace ? 'whitespace-pre-line' : undefined}
>
{children}
</Typography>
</div>

View File

@@ -9,7 +9,12 @@ export function Typography({
children,
italic = false,
}: {
variant?: 'main-title' | 'section-title' | 'standard' | 'vr-accessible';
variant?:
| 'main-title'
| 'section-title'
| 'standard'
| 'vr-accessible'
| 'mobile-title';
bold?: boolean;
italic?: boolean;
block?: boolean;
@@ -26,6 +31,7 @@ export function Typography({
const tags = {
'main-title': 'h1',
'section-title': 'h2',
'mobile-title': 'h1',
standard: 'p',
'vr-accessible': 'p',
};
@@ -37,6 +43,8 @@ export function Typography({
{
className: classNames([
'transition-colors',
variant === 'mobile-title' &&
'xs:text-main-title mobile:text-section-title',
variant === 'main-title' && 'text-main-title',
variant === 'section-title' && 'text-section-title',
variant === 'standard' &&

View File

@@ -0,0 +1,16 @@
export function DownloadIcon({ width = 22 }: { width?: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width={width}
className="fill-status-success stroke-status-success"
>
<path
fillRule="evenodd"
d="M12 2.25a.75.75 0 01.75.75v11.69l3.22-3.22a.75.75 0 111.06 1.06l-4.5 4.5a.75.75 0 01-1.06 0l-4.5-4.5a.75.75 0 111.06-1.06l3.22 3.22V3a.75.75 0 01.75-.75zm-9 13.5a.75.75 0 01.75.75v2.25a1.5 1.5 0 001.5 1.5h13.5a1.5 1.5 0 001.5-1.5V16.5a.75.75 0 011.5 0v2.25a3 3 0 01-3 3H5.25a3 3 0 01-3-3V16.5a.75.75 0 01.75-.75z"
clipRule="evenodd"
/>
</svg>
);
}

View File

@@ -1,32 +1,45 @@
import classNames from 'classnames';
export enum SlimeState {
HAPPY,
SAD,
JUMPY,
CURIOUS,
}
export function LoaderIcon({
youSpinMeRightRoundBabyRightRound = false,
slimeState = SlimeState.HAPPY,
}: {
youSpinMeRightRoundBabyRightRound?: boolean;
slimeState: SlimeState;
}) {
return (
<svg
width="20"
height="20"
viewBox="0 0 19 19"
xmlns="http://www.w3.org/2000/svg"
className={classNames({
'animate-spin': youSpinMeRightRoundBabyRightRound,
})}
>
<path d="M16.0312 8.90625H13.0625C12.7359 8.90625 12.4688 9.17344 12.4688 9.5C12.4688 9.82656 12.7359 10.0938 13.0625 10.0938H16.0312C16.3578 10.0938 16.625 9.82656 16.625 9.5C16.625 9.17344 16.3578 8.90625 16.0312 8.90625Z" />
<path d="M6.53125 9.5C6.53125 9.17344 6.26406 8.90625 5.9375 8.90625H2.96875C2.64219 8.90625 2.375 9.17344 2.375 9.5C2.375 9.82656 2.64219 10.0938 2.96875 10.0938H5.9375C6.26406 10.0938 6.53125 9.82656 6.53125 9.5Z" />
<path d="M9.5 12.4688C9.17344 12.4688 8.90625 12.7359 8.90625 13.0625V16.0312C8.90625 16.3578 9.17344 16.625 9.5 16.625C9.82656 16.625 10.0938 16.3578 10.0938 16.0312V13.0625C10.0938 12.7359 9.82656 12.4688 9.5 12.4688Z" />
<path d="M9.5 2.375C9.17344 2.375 8.90625 2.64219 8.90625 2.96875V5.9375C8.90625 6.26406 9.17344 6.53125 9.5 6.53125C9.82656 6.53125 10.0938 6.26406 10.0938 5.9375V2.96875C10.0938 2.64219 9.82656 2.375 9.5 2.375Z" />
<path d="M12.0716 8.01562C12.2349 8.30137 12.5986 8.39785 12.8843 8.23457L15.456 6.75019C15.7417 6.58691 15.8382 6.22324 15.6749 5.9375C15.5117 5.65176 15.148 5.55527 14.8623 5.71855L12.2906 7.20293C12.0048 7.36992 11.9083 7.72988 12.0716 8.01562Z" />
<path d="M6.92836 10.9844C6.76508 10.6986 6.40141 10.6021 6.11567 10.7654L3.54399 12.2498C3.25825 12.4131 3.16176 12.7768 3.32505 13.0625C3.48833 13.3482 3.852 13.4447 4.13774 13.2814L6.70942 11.7971C6.99516 11.6301 7.09165 11.2701 6.92836 10.9844Z" />
<path d="M11.7971 12.2869C11.6338 12.0012 11.2702 11.9047 10.9844 12.068C10.6987 12.2312 10.6022 12.5949 10.7655 12.8807L12.2498 15.4523C12.4131 15.7381 12.7768 15.8346 13.0625 15.6713C13.3483 15.508 13.4448 15.1443 13.2815 14.8586L11.7971 12.2869Z" />
<path d="M6.75024 3.54765C6.58696 3.26191 6.22329 3.16543 5.93754 3.32871C5.6518 3.49199 5.55532 3.85566 5.7186 4.1414L7.20297 6.71308C7.36626 6.99882 7.72993 7.09531 8.01567 6.93203C8.30141 6.76875 8.3979 6.40507 8.23461 6.11933L6.75024 3.54765Z" />
<path d="M10.9844 6.92832C11.2702 7.0916 11.6301 6.99512 11.7971 6.70937L13.2815 4.13769C13.4448 3.85195 13.3483 3.49199 13.0625 3.325C12.7768 3.16172 12.4168 3.2582 12.2498 3.54394L10.7655 6.11562C10.6022 6.40137 10.6987 6.76504 10.9844 6.92832Z" />
<path d="M8.01567 12.0717C7.72993 11.9084 7.36997 12.0049 7.20297 12.2906L5.7186 14.8623C5.55532 15.148 5.6518 15.508 5.93754 15.675C6.22329 15.8383 6.58325 15.7418 6.75024 15.456L8.23461 12.8844C8.3979 12.5986 8.30141 12.235 8.01567 12.0717Z" />
<path d="M15.4523 12.2498L12.8807 10.7654C12.5949 10.6021 12.235 10.6986 12.068 10.9844C11.9047 11.2701 12.0012 11.6301 12.2869 11.7971L14.8586 13.2814C15.1443 13.4447 15.5043 13.3482 15.6713 13.0625C15.8346 12.7768 15.7381 12.4168 15.4523 12.2498Z" />
<path d="M3.54765 6.75019L6.11933 8.23457C6.40507 8.39785 6.76504 8.30137 6.93203 8.01562C7.09902 7.72988 6.99882 7.36992 6.71308 7.20293L4.1414 5.71855C3.85566 5.55527 3.4957 5.65176 3.32871 5.9375C3.16543 6.22324 3.26191 6.5832 3.54765 6.75019Z" />
</svg>
<>
<img
hidden={slimeState !== SlimeState.JUMPY}
src="/images/jumping-slime.gif"
alt="Slime jumping"
width="85"
// className="crisp-edges"
></img>
<img
hidden={slimeState !== SlimeState.HAPPY}
src="/images/happy-slime.gif"
alt="Happy slime"
width="85"
// className="crisp-edges"
></img>
<img
hidden={slimeState !== SlimeState.SAD}
src="/images/sad-slime.gif"
alt="Sad slime"
width="85"
// className="crisp-edges"
></img>
<img
hidden={slimeState !== SlimeState.CURIOUS}
src="/images/curious-slime.gif"
alt="Slime looking for something"
width="85"
// className="crisp-edges"
></img>
</>
);
}

View File

@@ -0,0 +1,7 @@
export function PauseIcon({ width = 33 }: { width?: number }) {
return (
<svg width={width} height="29" viewBox="0 0 24 24">
<path d="M 5.9998494,-4.225e-5 A 2,2 0 0 0 3.9999715,1.9998356 V 22.000165 a 2,2 0 0 0 1.9998779,1.999877 2,2 0 0 0 1.999878,-1.999877 V 1.9998356 A 2,2 0 0 0 5.9998494,-4.225e-5 Z m 12.0003006,0 A 2,2 0 0 0 15.999756,1.9998356 V 22.000165 a 2,2 0 0 0 2.000394,1.999877 2,2 0 0 0 1.999878,-1.999877 V 1.9998356 A 2,2 0 0 0 18.00015,-4.225e-5 Z" />
</svg>
);
}

View File

@@ -0,0 +1,7 @@
export function PlayIcon({ width = 33 }: { width?: number }) {
return (
<svg width={width} height="29" viewBox="0 0 24 24">
<path d="M 4.8398087,0.31374371 21.480589,9.976131 a 2.3403036,2.3403036 0 0 1 0,4.047737 L 4.8398087,23.686256 A 2.3203976,2.3203976 0 0 1 1.354257,21.679602 V 2.3203979 A 2.3203976,2.3203976 0 0 1 4.8398087,0.31374371 Z" />
</svg>
);
}

View File

@@ -0,0 +1,17 @@
export function QuestionIcon({ width = 35 }: { width?: number }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
width={width}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"
/>
</svg>
);
}

View File

@@ -0,0 +1,31 @@
import classNames from 'classnames';
export function SpinIcon({
youSpinMeRightRoundBabyRightRound = false,
}: {
youSpinMeRightRoundBabyRightRound?: boolean;
}) {
return (
<svg
width="20"
viewBox="0 0 19 19"
xmlns="http://www.w3.org/2000/svg"
className={classNames({
'animate-spin': youSpinMeRightRoundBabyRightRound,
})}
>
<path d="M16.0312 8.90625H13.0625C12.7359 8.90625 12.4688 9.17344 12.4688 9.5C12.4688 9.82656 12.7359 10.0938 13.0625 10.0938H16.0312C16.3578 10.0938 16.625 9.82656 16.625 9.5C16.625 9.17344 16.3578 8.90625 16.0312 8.90625Z" />
<path d="M6.53125 9.5C6.53125 9.17344 6.26406 8.90625 5.9375 8.90625H2.96875C2.64219 8.90625 2.375 9.17344 2.375 9.5C2.375 9.82656 2.64219 10.0938 2.96875 10.0938H5.9375C6.26406 10.0938 6.53125 9.82656 6.53125 9.5Z" />
<path d="M9.5 12.4688C9.17344 12.4688 8.90625 12.7359 8.90625 13.0625V16.0312C8.90625 16.3578 9.17344 16.625 9.5 16.625C9.82656 16.625 10.0938 16.3578 10.0938 16.0312V13.0625C10.0938 12.7359 9.82656 12.4688 9.5 12.4688Z" />
<path d="M9.5 2.375C9.17344 2.375 8.90625 2.64219 8.90625 2.96875V5.9375C8.90625 6.26406 9.17344 6.53125 9.5 6.53125C9.82656 6.53125 10.0938 6.26406 10.0938 5.9375V2.96875C10.0938 2.64219 9.82656 2.375 9.5 2.375Z" />
<path d="M12.0716 8.01562C12.2349 8.30137 12.5986 8.39785 12.8843 8.23457L15.456 6.75019C15.7417 6.58691 15.8382 6.22324 15.6749 5.9375C15.5117 5.65176 15.148 5.55527 14.8623 5.71855L12.2906 7.20293C12.0048 7.36992 11.9083 7.72988 12.0716 8.01562Z" />
<path d="M6.92836 10.9844C6.76508 10.6986 6.40141 10.6021 6.11567 10.7654L3.54399 12.2498C3.25825 12.4131 3.16176 12.7768 3.32505 13.0625C3.48833 13.3482 3.852 13.4447 4.13774 13.2814L6.70942 11.7971C6.99516 11.6301 7.09165 11.2701 6.92836 10.9844Z" />
<path d="M11.7971 12.2869C11.6338 12.0012 11.2702 11.9047 10.9844 12.068C10.6987 12.2312 10.6022 12.5949 10.7655 12.8807L12.2498 15.4523C12.4131 15.7381 12.7768 15.8346 13.0625 15.6713C13.3483 15.508 13.4448 15.1443 13.2815 14.8586L11.7971 12.2869Z" />
<path d="M6.75024 3.54765C6.58696 3.26191 6.22329 3.16543 5.93754 3.32871C5.6518 3.49199 5.55532 3.85566 5.7186 4.1414L7.20297 6.71308C7.36626 6.99882 7.72993 7.09531 8.01567 6.93203C8.30141 6.76875 8.3979 6.40507 8.23461 6.11933L6.75024 3.54765Z" />
<path d="M10.9844 6.92832C11.2702 7.0916 11.6301 6.99512 11.7971 6.70937L13.2815 4.13769C13.4448 3.85195 13.3483 3.49199 13.0625 3.325C12.7768 3.16172 12.4168 3.2582 12.2498 3.54394L10.7655 6.11562C10.6022 6.40137 10.6987 6.76504 10.9844 6.92832Z" />
<path d="M8.01567 12.0717C7.72993 11.9084 7.36997 12.0049 7.20297 12.2906L5.7186 14.8623C5.55532 15.148 5.6518 15.508 5.93754 15.675C6.22329 15.8383 6.58325 15.7418 6.75024 15.456L8.23461 12.8844C8.3979 12.5986 8.30141 12.235 8.01567 12.0717Z" />
<path d="M15.4523 12.2498L12.8807 10.7654C12.5949 10.6021 12.235 10.6986 12.068 10.9844C11.9047 11.2701 12.0012 11.6301 12.2869 11.7971L14.8586 13.2814C15.1443 13.4447 15.5043 13.3482 15.6713 13.0625C15.8346 12.7768 15.7381 12.4168 15.4523 12.2498Z" />
<path d="M3.54765 6.75019L6.11933 8.23457C6.40507 8.39785 6.76504 8.30137 6.93203 8.01562C7.09902 7.72988 6.99882 7.36992 6.71308 7.20293L4.1414 5.71855C3.85566 5.55527 3.4957 5.65176 3.32871 5.9375C3.16543 6.22324 3.26191 6.5832 3.54765 6.75019Z" />
</svg>
);
}

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@ export function TrashIcon({ width = 33 }: { width: number }) {
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width={width}
height="24"
height="29"
>
<path
fillRule="evenodd"

View File

@@ -5,7 +5,8 @@ export function WarningIcon(props: any) {
viewBox="0 0 20 20"
fill="currentColor"
{...props}
className={`w-7 h-7 ${props.className || ''}`}
width={props.width || 30}
className={`${props.className || ''}`}
>
<path
fillRule="evenodd"

View File

@@ -1,16 +1,28 @@
import { useLocalization } from '@fluent/react';
import { useNavigate } from 'react-router-dom';
import { TrackerDataT } from 'solarxr-protocol';
import { Localized, useLocalization } from '@fluent/react';
import { NavLink, useNavigate } from 'react-router-dom';
import { StatusData, TrackerDataT } from 'solarxr-protocol';
import { useConfig } from '../../hooks/config';
import { useTrackers } from '../../hooks/tracker';
import { Typography } from '../commons/Typography';
import { TrackerCard } from '../tracker/TrackerCard';
import { TrackersTable } from '../tracker/TrackersTable';
import {
parseStatusToLocale,
trackerStatusRelated,
useStatusContext,
} from '../../hooks/status-system';
import { useMemo } from 'react';
import { WarningBox } from '../commons/TipBox';
import { HeadsetIcon } from '../commons/icon/HeadsetIcon';
import classNames from 'classnames';
const DONT_REPEAT_STATUSES = [StatusData.StatusTrackerReset];
export function Home() {
const { l10n } = useLocalization();
const { config } = useConfig();
const { trackers } = useTrackers();
const { statuses } = useStatusContext();
const navigate = useNavigate();
const sendToSettings = (tracker: TrackerDataT) => {
@@ -19,38 +31,81 @@ export function Home() {
);
};
return (
<div className="overflow-y-auto flex flex-col gap-2">
{trackers.length === 0 && (
<div className="flex px-5 pt-5 justify-center">
<Typography variant="standard">
{l10n.getString('home-no_trackers')}
</Typography>
</div>
)}
const filteredStatuses = useMemo(() => {
const dontRepeat = new Map(DONT_REPEAT_STATUSES.map((x) => [x, false]));
return Object.entries(statuses).filter(([, value]) => {
if (dontRepeat.get(value.dataType)) return false;
if (dontRepeat.has(value.dataType)) dontRepeat.set(value.dataType, true);
return true;
});
}, [statuses]);
{!config?.debug && trackers.length > 0 && (
<div className="grid sm:grid-cols-1 md:grid-cols-2 gap-3 px-4 my-4">
{trackers.map(({ tracker, device }, index) => (
<TrackerCard
key={index}
tracker={tracker}
device={device}
onClick={() => sendToSettings(tracker)}
smol
interactable
/>
))}
return (
<div className="relative h-full">
<NavLink
to="/vr-mode"
className="xs:hidden absolute z-50 h-12 w-12 rounded-full bg-accent-background-30 bottom-3 right-3 flex justify-center items-center fill-background-10"
>
<HeadsetIcon></HeadsetIcon>
</NavLink>
<div className="h-full overflow-y-auto">
<div
className={classNames(
'px-2 pt-4 gap-3 w-full grid md:grid-cols-2 mobile:grid-cols-1',
filteredStatuses.filter(([, status]) => status.prioritized)
.length === 0 && 'hidden'
)}
>
{filteredStatuses
.filter(([, status]) => status.prioritized)
.map(([, status]) => (
<Localized
key={status.id}
id={`status_system-${StatusData[status.dataType]}`}
vars={parseStatusToLocale(status, trackers, l10n)}
>
<WarningBox whitespace={false}>
{`Warning, you should fix ${StatusData[status.dataType]}`}
</WarningBox>
</Localized>
))}
</div>
)}
{config?.debug && trackers.length > 0 && (
<div className="px-2 pt-5 overflow-y-scroll overflow-x-auto">
<TrackersTable
flatTrackers={trackers}
clickedTracker={(tracker) => sendToSettings(tracker)}
></TrackersTable>
<div className="overflow-y-auto flex flex-col gap-2">
{trackers.length === 0 && (
<div className="flex px-5 pt-5 justify-center">
<Typography variant="standard">
{l10n.getString('home-no_trackers')}
</Typography>
</div>
)}
{!config?.debug && trackers.length > 0 && (
<div className="grid sm:grid-cols-1 md:grid-cols-2 gap-3 px-2 my-2">
{trackers.map(({ tracker, device }, index) => (
<TrackerCard
key={index}
tracker={tracker}
device={device}
onClick={() => sendToSettings(tracker)}
smol
interactable
warning={Object.values(statuses).some((status) =>
trackerStatusRelated(tracker, status)
)}
/>
))}
</div>
)}
{config?.debug && trackers.length > 0 && (
<div className="px-2 pt-5 overflow-y-scroll overflow-x-auto">
<TrackersTable
flatTrackers={trackers}
clickedTracker={(tracker) => sendToSettings(tracker)}
></TrackersTable>
</div>
)}
</div>
)}
</div>
</div>
);
}

View File

@@ -33,6 +33,7 @@ export function ResetButton({
};
const { isCounting, startCountdown, timer } = useCountdown({
duration: type === ResetType.Yaw ? 0.2 : undefined,
onCountdownEnd: () => {
reset();
if (onReseted) onReseted();
@@ -66,55 +67,33 @@ export function ResetButton({
};
const variantsMap = {
small:
type == ResetType.Yaw ? (
<Button
icon={getIcon()}
onClick={() => {
reset();
maybePlaySoundOnResetStarted(type);
}}
variant="primary"
>
{text}
</Button>
) : (
<Button
icon={getIcon()}
onClick={() => {
startCountdown();
maybePlaySoundOnResetStarted(type);
}}
variant="primary"
disabled={isCounting}
>
<div className="relative">
<div className="opacity-0 h-0">{text}</div>
{!isCounting ? text : String(timer)}
</div>
</Button>
),
big:
type == ResetType.Yaw ? (
<BigButton
text={text}
icon={getIcon()}
onClick={() => {
reset();
maybePlaySoundOnResetStarted(type);
}}
></BigButton>
) : (
<BigButton
text={!isCounting ? text : String(timer)}
icon={getIcon()}
onClick={() => {
startCountdown();
maybePlaySoundOnResetStarted(type);
}}
disabled={isCounting}
></BigButton>
),
small: (
<Button
icon={getIcon()}
onClick={() => {
startCountdown();
maybePlaySoundOnResetStarted(type);
}}
variant="primary"
disabled={isCounting}
>
<div className="relative">
<div className="opacity-0 h-0">{text}</div>
{!isCounting || type === ResetType.Yaw ? text : String(timer)}
</div>
</Button>
),
big: (
<BigButton
text={!isCounting || type === ResetType.Yaw ? text : String(timer)}
icon={getIcon()}
onClick={() => {
startCountdown();
maybePlaySoundOnResetStarted(type);
}}
disabled={isCounting}
></BigButton>
),
};
return variantsMap[variant];

View File

@@ -34,12 +34,14 @@ export function BodyAssignment({
rolesWithErrors = {},
highlightedRoles = [],
onlyAssigned = false,
width,
}: {
advanced: boolean;
onlyAssigned: boolean;
onlyAssigned?: boolean;
rolesWithErrors?: Partial<Record<BodyPart, BodyPartError>>;
highlightedRoles?: BodyPart[];
onRoleSelected: (role: BodyPart) => void;
width?: number;
}) {
const { useAssignedTrackers } = useTrackers();
@@ -74,6 +76,7 @@ export function BodyAssignment({
return (
<>
<BodyInteractions
width={width}
assignedRoles={assignedRoles}
highlightedRoles={highlightedRoles}
onSelectRole={onRoleSelected}

View File

@@ -3,9 +3,11 @@ import { useLayout } from '../../hooks/layout';
import { useOnboarding } from '../../hooks/onboarding';
import { MainLayoutRoute } from '../MainLayout';
import { TopBar } from '../TopBar';
import { useBreakpoint } from '../../hooks/breakpoint';
export function OnboardingLayout({ children }: { children: ReactNode }) {
const { layoutHeight, ref } = useLayout<HTMLDivElement>();
const { isMobile } = useBreakpoint('mobile');
const { state } = useOnboarding();
return !state.alonePage ? (
@@ -13,15 +15,15 @@ export function OnboardingLayout({ children }: { children: ReactNode }) {
<TopBar progress={state.progress}></TopBar>
<div
ref={ref}
className="flex-grow pt-10 mx-4"
className="flex-grow xs:pt-10 mobile:pt-2"
style={{ height: layoutHeight }}
>
{children}
</div>
</>
) : (
<MainLayoutRoute widgets={false}>
<div className="flex-grow pt-10 mx-4">{children}</div>
<MainLayoutRoute widgets={false} isMobile={isMobile}>
<div className="flex-grow xs:pt-10 mobile:pt-2">{children}</div>
</MainLayoutRoute>
);
}

View File

@@ -30,7 +30,7 @@ export function SkipSetupButton({
className={classNames(
'text-background-40 hover:text-background-30',
'stroke-background-40 hover:stroke-background-30',
'absolute -top-10 right-0'
'absolute xs:-top-10 xs:right-4 mobile:top-0 mobile:right-0'
)}
onClick={onClick}
>

View File

@@ -39,7 +39,7 @@ export function SkipSetupWarningModal({
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">
<div className="flex flex-col flex-grow items-center gap-3">
<Localized id="onboarding-setup_warning" elems={{ b: <b></b> }}>
<WarningBox>
<b>Warning:</b> The setup is needed for good tracking, this is
@@ -52,7 +52,7 @@ export function SkipSetupWarningModal({
{l10n.getString('onboarding-setup_warning-cancel')}
</Button>
<Button
variant="tiertiary"
variant="tertiary"
onClick={() => {
accept();
navigate('/');

View File

@@ -40,7 +40,7 @@ export function StepContainer({
return (
<div
className={classNames(
'step-container transition-transform duration-500 w-full p-8 rounded-lg flex gap-4 h-full',
'step-container transition-transform duration-500 relative w-full xs:p-8 mobile:p-2 rounded-lg flex gap-4 h-full',
!active && 'opacity-40 pointer-events-none',
variant === 'onboarding' && 'bg-background-70',
variant === 'alone' && 'bg-background-60'
@@ -51,7 +51,7 @@ export function StepContainer({
}}
>
{type === 'numbered' && (
<div className="flex flex-col">
<div className="xs:flex xs:flex-col mobile:absolute mobile:-top-3 mobile:-right-4">
<div className="bg-accent-background-40 rounded-full h-8 w-8 flex flex-col items-center justify-center">
<Typography variant="section-title" bold>
{step + 1}

View File

@@ -0,0 +1,171 @@
import { Localized, useLocalization } from '@fluent/react';
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';
import classNames from 'classnames';
import { TaybolIcon } from '../../commons/icon/TaybolIcon';
export enum CalibrationStatus {
SUCCESS,
CALIBRATING,
WAITING,
ERROR,
}
export const IMU_CALIBRATION_TIME = 4;
export function CalibrationTutorialPage() {
const { l10n } = useLocalization();
const { applyProgress, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const [calibrationStatus, setCalibrationStatus] = useState(
CalibrationStatus.WAITING
);
const { timer, isCounting, startCountdown } = useCountdown({
duration: IMU_CALIBRATION_TIME,
onCountdownEnd: () => setCalibrationStatus(CalibrationStatus.SUCCESS),
});
const progressBarClass = useMemo(() => {
switch (calibrationStatus) {
case CalibrationStatus.ERROR:
return 'bg-status-critical';
case CalibrationStatus.SUCCESS:
return 'bg-status-success';
}
}, [calibrationStatus]);
const slimeStatus = useMemo(() => {
switch (calibrationStatus) {
case CalibrationStatus.CALIBRATING:
return SlimeState.JUMPY;
case CalibrationStatus.ERROR:
return SlimeState.SAD;
default:
return SlimeState.HAPPY;
}
}, [calibrationStatus]);
const progressText = useMemo(() => {
switch (calibrationStatus) {
case CalibrationStatus.CALIBRATING:
return l10n.getString(
'onboarding-calibration_tutorial-status-calibrating'
);
case CalibrationStatus.ERROR:
return l10n.getString('onboarding-calibration_tutorial-status-error');
case CalibrationStatus.SUCCESS:
return l10n.getString('onboarding-calibration_tutorial-status-success');
case CalibrationStatus.WAITING:
return l10n.getString('onboarding-calibration_tutorial-status-waiting');
}
}, [calibrationStatus, l10n]);
applyProgress(0.43);
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">
<div>
<Typography variant="mobile-title">
{l10n.getString('onboarding-calibration_tutorial')}
</Typography>
<Typography variant="vr-accessible" italic>
{l10n.getString('onboarding-calibration_tutorial-subtitle')}
</Typography>
</div>
<Localized
id="onboarding-calibration_tutorial-description"
elems={{ b: <b></b> }}
>
<Typography color="secondary">
Description on calibration of IMU
</Typography>
</Localized>
<div>
<div className="xs:hidden flex flex-row justify-center">
<div className="stroke-none fill-background-10 ">
<TaybolIcon width="220"></TaybolIcon>
</div>
</div>
<div className="flex justify-center">
<LoaderIcon slimeState={slimeStatus}></LoaderIcon>
</div>
<ProgressBar
progress={
isCounting
? (IMU_CALIBRATION_TIME - timer) / IMU_CALIBRATION_TIME
: calibrationStatus === CalibrationStatus.SUCCESS
? 1
: 0
}
height={14}
animated={true}
colorClass={progressBarClass}
></ProgressBar>
</div>
<div className="flex justify-center">
<Typography variant="section-title">{progressText}</Typography>
</div>
<div className="flex gap-3 mobile:flex-col">
<Button
variant="secondary"
to="/onboarding/wifi-creds"
className="xs:mr-auto"
>
{l10n.getString('onboarding-previous_step')}
</Button>
<Button
variant="primary"
onClick={() => {
setCalibrationStatus(CalibrationStatus.CALIBRATING);
startCountdown();
}}
disabled={isCounting}
hidden={CalibrationStatus.SUCCESS === calibrationStatus}
className="xs:ml-auto"
>
{l10n.getString('onboarding-calibration_tutorial-calibrate')}
</Button>
<Button
variant="primary"
to="/onboarding/assign-tutorial"
className={classNames(
'xs:ml-auto',
CalibrationStatus.SUCCESS !== calibrationStatus && 'hidden'
)}
>
{l10n.getString('onboarding-continue')}
</Button>
</div>
</div>
</div>
<div className="mobile:hidden flex self-center w-[32rem] mobile:absolute">
<div className="stroke-none xs:fill-background-10 mobile:fill-background-50 mobile:blur-sm">
<TaybolIcon width="500"></TaybolIcon>
</div>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
</>
);
}

View File

@@ -15,13 +15,15 @@ import { useTrackers } from '../../../hooks/tracker';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { ArrowLink } from '../../commons/ArrowLink';
import { Button } from '../../commons/Button';
import { LoaderIcon } from '../../commons/icon/LoaderIcon';
import { LoaderIcon, SlimeState } from '../../commons/icon/LoaderIcon';
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';
const BOTTOM_HEIGHT = 80;
@@ -56,9 +58,12 @@ const statusProgressMap = {
};
export function ConnectTrackersPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { layoutHeight, ref } = useLayout<HTMLDivElement>();
const { trackers, useConnectedTrackers } = useTrackers();
const { layoutHeight, ref } = isMobile
? { layoutHeight: 0, ref: undefined }
: useLayout<HTMLDivElement>();
const { useConnectedTrackers } = useTrackers();
const { applyProgress, state, skipSetup } = useOnboarding();
const navigate = useNavigate();
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
@@ -70,6 +75,8 @@ export function ConnectTrackersPage() {
const connectedTrackers = useConnectedTrackers();
const bnoExists = useBnoExists(connectedTrackers);
useEffect(() => {
if (!state.wifi) {
navigate('/onboarding/wifi-creds');
@@ -109,14 +116,29 @@ export function ConnectTrackersPage() {
}
}, [provisioningStatus]);
const slimeStatus = useMemo(() => {
if (isError) {
return SlimeState.SAD;
}
switch (provisioningStatus) {
case WifiProvisioningStatus.DONE:
return SlimeState.HAPPY;
case WifiProvisioningStatus.NONE:
return SlimeState.CURIOUS;
default:
return SlimeState.JUMPY;
}
}, [provisioningStatus]);
return (
<div className="flex flex-col items-center relative">
<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 gap-10 w-full max-w-7xl ">
<div className="flex gap-10 mobile:flex-col w-full xs:max-w-7xl">
<div className="flex flex-col w-full max-w-sm">
<Typography variant="main-title">
{l10n.getString('onboarding-connect_tracker-title')}
@@ -148,47 +170,66 @@ export function ConnectTrackersPage() {
<div
className={classNames(
'rounded-xl h-16 flex gap-2 p-3 lg:w-full mt-4',
'rounded-xl h-24 flex gap-2 p-3 lg:w-full mt-4 relative',
state.alonePage ? 'bg-background-60' : 'bg-background-70',
isError && 'border-2 border-status-critical'
)}
>
<div className="flex flex-col justify-center fill-background-10">
<LoaderIcon
youSpinMeRightRoundBabyRightRound={!isError}
></LoaderIcon>
<div
className={classNames(
'flex flex-col justify-center fill-background-10 absolute',
'right-5 bottom-8'
)}
>
<LoaderIcon slimeState={slimeStatus}></LoaderIcon>
</div>
<div className="flex flex-col grow">
<div className="flex flex-col grow self-center">
<Typography bold>
{l10n.getString('onboarding-connect_tracker-usb')}
</Typography>
<Typography color="secondary">
{l10n.getString(statusLabelMap[provisioningStatus])}
</Typography>
<div className="flex fill-background-10 gap-1">
{/* <SpinIcon
youSpinMeRightRoundBabyRightRound={!isError}
></SpinIcon> */}
<Typography color="secondary">
{l10n.getString(statusLabelMap[provisioningStatus])}
</Typography>
</div>
<ProgressBar
progress={statusProgressMap[provisioningStatus]}
height={6}
height={14}
animated={true}
colorClass={progressBarClass}
></ProgressBar>
</div>
</div>
<div className="flex flex-row mt-4">
{!state.alonePage && (
<Button variant="secondary" to="/onboarding/wifi-creds">
{l10n.getString('onboarding-previous_step')}
</Button>
)}
<div className="flex flex-row mt-4 gap-3">
<Button
variant="secondary"
state={{ alonePage: state.alonePage }}
to="/onboarding/wifi-creds"
>
{state.alonePage
? l10n.getString('onboarding-connect_tracker-back')
: l10n.getString('onboarding-previous_step')}
</Button>
<Button
variant="primary"
to={state.alonePage ? '/' : '/onboarding/trackers-assign'}
to={
state.alonePage
? '/'
: bnoExists
? '/onboarding/calibration-tutorial'
: '/onboarding/assign-tutorial'
}
className="ml-auto"
>
{l10n.getString('onboarding-connect_tracker-next')}
</Button>
</div>
</div>
<div className="flex flex-col flex-grow">
<div className="flex flex-col xs:flex-grow">
<Typography color="secondary" bold>
{l10n.getString('onboarding-connect_tracker-connected_trackers', {
amount: connectedTrackers.length,
@@ -196,20 +237,20 @@ export function ConnectTrackersPage() {
</Typography>
<div
className="flex-grow overflow-y-scroll"
className="xs:flex-grow xs:overflow-y-scroll"
ref={ref}
style={{ height: layoutHeight - BOTTOM_HEIGHT }}
style={isMobile ? { height: layoutHeight - BOTTOM_HEIGHT } : {}}
>
<div className="grid lg:grid-cols-2 md:grid-cols-1 gap-2 mx-3 pt-3">
<div className="grid lg:grid-cols-2 md:grid-cols-1 gap-2 xs:mx-3 pt-3">
{Array.from({
...connectedTrackers,
length: Math.max(trackers.length, 20),
length: Math.max(connectedTrackers.length, isMobile ? 1 : 20),
}).map((tracker, index) => (
<div key={index}>
{!tracker && (
<div
className={classNames(
'rounded-xl h-16',
'rounded-xl h-16 mobile:animate-pulse',
state.alonePage
? 'bg-background-80'
: 'bg-background-70'

View File

@@ -17,7 +17,7 @@ export function HomePage() {
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative">
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative px-4">
<SkipSetupButton
visible={true}
modalVisible={skipWarning}
@@ -25,14 +25,14 @@ export function HomePage() {
></SkipSetupButton>
<div className="flex flex-col gap-5 items-center z-10 scale-150 mb-20">
<SlimeVRIcon></SlimeVRIcon>
<Typography variant="main-title">
<Typography variant="mobile-title">
{l10n.getString('onboarding-home')}
</Typography>
<Button variant="primary" to="/onboarding/wifi-creds">
{l10n.getString('onboarding-home-start')}
</Button>
</div>
<div className="absolute right-0 bottom-4 z-50">
<div className="absolute right-4 bottom-4 z-50">
<LangSelector />
</div>
<div

View File

@@ -2,58 +2,222 @@ 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 { useState, useMemo, useEffect } from 'react';
import { SkipSetupWarningModal } from '../SkipSetupWarningModal';
import { SkipSetupButton } from '../SkipSetupButton';
import {
BodyPart,
ResetResponseT,
ResetStatus,
ResetType,
RpcMessage,
SettingsRequestT,
SettingsResponseT,
} from 'solarxr-protocol';
import { useTrackers } from '../../../hooks/tracker';
import { BodyDisplay } from '../../commons/BodyDisplay';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import classNames from 'classnames';
import { useBreakpoint } from '../../../hooks/breakpoint';
export function ResetTutorialPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { applyProgress, skipSetup } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { useAssignedTrackers } = useTrackers();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [curIndex, setCurIndex] = useState(0);
const [tapSettings, setTapSettings] = useState<number[]>([]);
applyProgress(0.8);
const assignedTrackers = useAssignedTrackers();
const highestTorsoTracker = useMemo(
() =>
assignedTrackers
.filter((x) =>
TORSO_PARTS.includes(x.tracker.info?.bodyPart ?? BodyPart.NONE)
)
.sort(
(a, b) =>
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
TORSO_PARTS.indexOf(a.tracker.info!.bodyPart)! -
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
TORSO_PARTS.indexOf(b.tracker.info!.bodyPart)!
),
[assignedTrackers]
);
const highestRightLegTracker = useMemo(
() =>
assignedTrackers
.filter((x) =>
RIGHT_LEG_PARTS.includes(x.tracker.info?.bodyPart ?? BodyPart.NONE)
)
.sort(
(a, b) =>
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
RIGHT_LEG_PARTS.indexOf(a.tracker.info!.bodyPart)! -
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
RIGHT_LEG_PARTS.indexOf(b.tracker.info!.bodyPart)!
),
[assignedTrackers]
);
const highestLeftLegTracker = useMemo(
() =>
assignedTrackers
.filter((x) =>
LEFT_LEG_PARTS.includes(x.tracker.info?.bodyPart ?? BodyPart.NONE)
)
.sort(
(a, b) =>
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
LEFT_LEG_PARTS.indexOf(a.tracker.info!.bodyPart)! -
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
LEFT_LEG_PARTS.indexOf(b.tracker.info!.bodyPart)!
),
[assignedTrackers]
);
useRPCPacket(
RpcMessage.ResetResponse,
({ status, resetType }: ResetResponseT) => {
if (status !== ResetStatus.STARTED) return;
console.log(status);
if (resetType === RESET_TYPE_ORDER[curIndex]) {
setCurIndex(curIndex + 1);
}
}
);
useEffect(() => {
sendRPCPacket(RpcMessage.SettingsRequest, new SettingsRequestT());
}, []);
useRPCPacket(
RpcMessage.SettingsResponse,
({ tapDetectionSettings }: SettingsResponseT) => {
if (
!tapDetectionSettings ||
!tapDetectionSettings.yawResetTaps ||
!tapDetectionSettings.fullResetTaps ||
!tapDetectionSettings.mountingResetTaps
)
return;
setTapSettings([
tapDetectionSettings.yawResetTaps,
tapDetectionSettings.fullResetTaps,
tapDetectionSettings.mountingResetTaps,
]);
}
);
const order = [
highestTorsoTracker[0],
highestLeftLegTracker[0],
highestRightLegTracker[0],
];
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 px-20">
<div className="flex gap-8 self-center">
<div className="flex flex-col max-w-md gap-3">
<Typography variant="main-title">
{l10n.getString('onboarding-reset_tutorial')}
<span className="mx-2 p-1 bg-accent-background-30 text-standard rounded-md">
{l10n.getString('onboarding-wip')}
</span>
</Typography>
<Typography color="secondary">
{l10n.getString('onboarding-reset_tutorial-description')}
</Typography>
<div className="flex">
<Button variant="secondary" to="/onboarding/mounting/choose">
{l10n.getString('onboarding-previous_step')}
</Button>
<Button
variant="primary"
to="/onboarding/body-proportions/choose"
className="ml-auto"
>
{l10n.getString('onboarding-continue')}
</Button>
</div>
</div>
<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')}
</Typography>
<div className="flex">
<Button variant="secondary" to="/onboarding/mounting/choose">
{l10n.getString('onboarding-previous_step')}
</Button>
<Button
hidden={curIndex + 1 >= order.length}
variant="secondary"
className="ml-auto"
onClick={() => {
setCurIndex(curIndex + 1);
}}
>
{l10n.getString('onboarding-reset_tutorial-skip')}
</Button>
<Button
variant="primary"
to="/onboarding/body-proportions/choose"
className={classNames(
'ml-auto',
order.length > curIndex + 1 && 'hidden'
)}
>
{l10n.getString('onboarding-continue')}
</Button>
</div>
<div
className={classNames(
'self-center xs:w-72 md:hidden xs:mt-10 mobile:mt-5 xs:ml-auto border-background-10',
'border-l-4 pl-4',
curIndex < order.length && 'visible',
curIndex >= order.length && 'hidden'
)}
>
<Typography whitespace="whitespace-pre-line" color="secondary">
{l10n.getString(`onboarding-reset_tutorial-${curIndex}`, {
taps: tapSettings[curIndex],
})}
</Typography>
</div>
</div>
<div className="flex flex-row justify-center">
<BodyDisplay
width={isMobile ? 160 : undefined}
trackers={[order[curIndex]]}
hideUnassigned={true}
></BodyDisplay>
<div
className={classNames(
'self-center w-72 md-max:hidden',
curIndex >= order.length && 'hidden'
)}
>
<Typography whitespace="whitespace-pre-line" color="secondary">
{l10n.getString(`onboarding-reset_tutorial-${curIndex}`, {
taps: tapSettings[curIndex],
})}
</Typography>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
</>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
);
}
export const TORSO_PARTS = [BodyPart.CHEST, BodyPart.WAIST, BodyPart.HIP];
export const LEFT_LEG_PARTS = [
BodyPart.LEFT_UPPER_LEG,
BodyPart.LEFT_LOWER_LEG,
];
export const RIGHT_LEG_PARTS = [
BodyPart.RIGHT_UPPER_LEG,
BodyPart.RIGHT_LOWER_LEG,
];
export const RESET_TYPE_ORDER = [
ResetType.Yaw,
ResetType.Full,
ResetType.Mounting,
];

View File

@@ -7,27 +7,34 @@ 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 } = useOnboarding();
const { applyProgress, skipSetup, state } = useOnboarding();
const { control, handleSubmit, submitWifiCreds, formState } = useWifiForm();
const { useConnectedTrackers } = useTrackers();
const [skipWarning, setSkipWarning] = useState(false);
const connectedTrackers = useConnectedTrackers();
applyProgress(0.2);
const bnoExists = useBnoExists(connectedTrackers);
return (
<form
className="flex flex-col w-full h-full"
onSubmit={handleSubmit(submitWifiCreds)}
>
<div className="flex flex-col w-full h-full justify-center items-center relative">
<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 gap-10">
<div className="flex mobile:flex-col xs:gap-10 px-4">
<div className="flex flex-col max-w-sm">
<Typography variant="main-title">
{l10n.getString('onboarding-wifi_creds')}
@@ -42,15 +49,23 @@ export function WifiCredsPage() {
</Typography>
))}
</>
<Button
variant="secondary"
to="/onboarding/home"
className="mt-auto mb-10 self-start"
>
{l10n.getString('onboarding-previous_step')}
</Button>
{!state.alonePage && (
<Button
variant="secondary"
to="/onboarding/home"
className="mt-auto mb-10 self-start"
>
{l10n.getString('onboarding-previous_step')}
</Button>
)}
</div>
<div className="flex flex-col bg-background-70 gap-3 p-10 rounded-xl max-w-sm">
<div
className={classNames(
'flex flex-col gap-3 p-10 rounded-xl max-w-sm',
!state.alonePage && 'bg-background-70',
state.alonePage && 'bg-background-60'
)}
>
<Localized
id="onboarding-wifi_creds-ssid"
attrs={{ placeholder: true, label: true }}
@@ -80,7 +95,15 @@ export function WifiCredsPage() {
/>
</Localized>
<div className="flex flex-row gap-3">
<Button variant="secondary" to="/onboarding/trackers-assign">
<Button
variant="secondary"
className={state.alonePage ? 'opacity-0' : ''}
to={
bnoExists
? '/onboarding/calibration-tutorial'
: '/onboarding/assign-tutorial'
}
>
{l10n.getString('onboarding-wifi_creds-skip')}
</Button>
<Button

View File

@@ -0,0 +1,106 @@
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';
import { TrackerArrow } from './TrackerArrow';
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);
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>
<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>
</div>
</div>
<SkipSetupWarningModal
accept={skipSetup}
onClose={() => setSkipWarning(false)}
isOpen={skipWarning}
></SkipSetupWarningModal>
</div>
</>
);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,10 @@
import { useLocalization } from '@fluent/react';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { RpcMessage, SkeletonResetAllRequestT } from 'solarxr-protocol';
import {
AutoboneContextC,
useProvideAutobone,
} from '../../../../hooks/autobone';
import { useBodyProportions } from '../../../../hooks/body-proportions';
import { useOnboarding } from '../../../../hooks/onboarding';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import { Button } from '../../../commons/Button';
@@ -26,7 +25,6 @@ export function AutomaticProportionsPage() {
const { applyProgress, skipSetup, state } = useOnboarding();
const { sendRPCPacket } = useWebsocketAPI();
const context = useProvideAutobone();
const { onPageOpened } = useBodyProportions();
const [skipWarning, setSkipWarning] = useState(false);
const { isCounting, startCountdown, timer } = useCountdown({
onCountdownEnd: () => {
@@ -39,13 +37,9 @@ export function AutomaticProportionsPage() {
applyProgress(0.9);
useEffect(() => {
onPageOpened();
}, []);
return (
<AutoboneContextC.Provider value={context}>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative">
<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}
@@ -76,21 +70,19 @@ export function AutomaticProportionsPage() {
></StepperSlider>
</div>
</div>
<div className="w-full pb-4 flex flex-row">
<div className="flex flex-grow gap-3">
<Button
variant="secondary"
onClick={startCountdown}
disabled={isCounting}
>
<div className="relative">
<div className="opacity-0 h-0">
{l10n.getString('reset-reset_all')}
</div>
{!isCounting ? l10n.getString('reset-reset_all') : timer}
<div className="w-full pb-4 flex flex-grow flex-row mobile:justify-center">
<Button
variant="secondary"
onClick={startCountdown}
disabled={isCounting}
>
<div className="relative">
<div className="opacity-0 h-0">
{l10n.getString('reset-reset_all')}
</div>
</Button>
</div>
{!isCounting ? l10n.getString('reset-reset_all') : timer}
</div>
</Button>
</div>
</div>
<SkipSetupWarningModal

View File

@@ -8,6 +8,7 @@ import {
} from '../../../../hooks/manual-proportions';
import { useLocaleConfig } from '../../../../i18n/config';
import { Typography } from '../../../commons/Typography';
import { useBreakpoint } from '../../../../hooks/breakpoint';
function IncrementButton({
children,
@@ -20,10 +21,10 @@ function IncrementButton({
<div
onClick={onClick}
className={classNames(
'p-3 rounded-lg w-16 h-16 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'
)}
>
<Typography variant="main-title" bold>
<Typography variant="mobile-title" bold>
{children}
</Typography>
</div>
@@ -39,6 +40,8 @@ export function BodyProportions({
type: 'linear' | 'ratio';
variant: 'onboarding' | 'alone';
}) {
const { isMobile } = useBreakpoint('mobile');
const [bodyParts, _ratioMode, currentSelection, dispatch, setRatioMode] =
useManualProportions();
const { currentLocales } = useLocaleConfig();
@@ -69,8 +72,8 @@ export function BodyProportions({
<div className="relative w-full">
<div
className={classNames(
'flex flex-col overflow-y-scroll overflow-x-hidden max-h-[450px] h-[54vh]',
'w-full px-1 gap-3 gradient-mask-b-90'
'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'
)}
>
<>
@@ -79,7 +82,7 @@ export function BodyProportions({
'index' in props && props.index !== undefined
? props.bones[props.index].value
: originalValue;
const selected = currentSelection.label === label;
const selected = isMobile || currentSelection.label === label;
const selectNew = () => {
switch (type) {
@@ -130,8 +133,9 @@ export function BodyProportions({
>
{!precise && (
<IncrementButton
onClick={() =>
type === LabelType.GroupPart
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.05,
@@ -139,15 +143,16 @@ export function BodyProportions({
: dispatch({
type: ProportionChangeType.Linear,
value: -5,
})
}
});
}}
>
{configFormat.format(-5)}
</IncrementButton>
)}
<IncrementButton
onClick={() =>
type === LabelType.GroupPart
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.01,
@@ -155,15 +160,16 @@ export function BodyProportions({
: dispatch({
type: ProportionChangeType.Linear,
value: -1,
})
}
});
}}
>
{configFormat.format(-1)}
</IncrementButton>
{precise && (
<IncrementButton
onClick={() =>
type === LabelType.GroupPart
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: -0.005,
@@ -171,8 +177,8 @@ export function BodyProportions({
: dispatch({
type: ProportionChangeType.Linear,
value: -0.5,
})
}
});
}}
>
{configFormat.format(-0.5)}
</IncrementButton>
@@ -185,14 +191,14 @@ export function BodyProportions({
<div
key={label}
className={classNames(
'p-3 rounded-lg h-16 flex w-full items-center justify-between px-6 transition-colors duration-300 bg-background-60',
'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'
)}
>
<Typography variant="section-title" bold>
{l10n.getString(label)}
</Typography>
<Typography variant="main-title" bold>
<Typography variant="mobile-title" bold>
{type === LabelType.GroupPart
? /* Make number rounding so it's based on .5 decimals */
percentageFormat.format(Math.round(value * 200) / 200)
@@ -213,8 +219,9 @@ export function BodyProportions({
>
{precise && (
<IncrementButton
onClick={() =>
type === LabelType.GroupPart
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.005,
@@ -222,15 +229,16 @@ export function BodyProportions({
: dispatch({
type: ProportionChangeType.Linear,
value: 0.5,
})
}
});
}}
>
{configFormat.format(+0.5)}
</IncrementButton>
)}
<IncrementButton
onClick={() =>
type === LabelType.GroupPart
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.01,
@@ -238,15 +246,16 @@ export function BodyProportions({
: dispatch({
type: ProportionChangeType.Linear,
value: 1,
})
}
});
}}
>
{configFormat.format(+1)}
</IncrementButton>
{!precise && (
<IncrementButton
onClick={() =>
type === LabelType.GroupPart
onClick={() => {
selectNew();
return type === LabelType.GroupPart
? dispatch({
type: ProportionChangeType.Ratio,
value: 0.05,
@@ -254,8 +263,8 @@ export function BodyProportions({
: dispatch({
type: ProportionChangeType.Linear,
value: 5,
})
}
});
}}
>
{configFormat.format(+5)}
</IncrementButton>

View File

@@ -9,15 +9,47 @@ import { Typography } from '../../../commons/Typography';
import { BodyProportions } from './BodyProportions';
import { useLocalization } from '@fluent/react';
import { useEffect, useMemo, useState } from 'react';
import { useBodyProportions } from '../../../../hooks/body-proportions';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupButton } from '../../SkipSetupButton';
import { useBreakpoint } from '../../../../hooks/breakpoint';
export function ButtonsControl() {
const { l10n } = useLocalization();
const { state } = useOnboarding();
const { sendRPCPacket } = useWebsocketAPI();
const resetAll = () => {
sendRPCPacket(
RpcMessage.SkeletonResetAllRequest,
new SkeletonResetAllRequestT()
);
};
return (
<>
<Button
variant="secondary"
state={{ alonePage: state.alonePage }}
to="/onboarding/body-proportions/choose"
>
{l10n.getString('onboarding-previous_step')}
</Button>
<Button variant="secondary" onClick={resetAll}>
{l10n.getString('reset-reset_all')}
</Button>
{!state.alonePage && (
<Button variant="primary" className="ml-auto" to="/onboarding/done">
{l10n.getString('onboarding-continue')}
</Button>
)}
</>
);
}
export function ManualProportionsPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const { sendRPCPacket } = useWebsocketAPI();
const { onPageOpened } = useBodyProportions();
const [skipWarning, setSkipWarning] = useState(false);
applyProgress(0.9);
@@ -29,32 +61,21 @@ export function ManualProportionsPage() {
});
const { precise, ratio } = watch();
const resetAll = () => {
sendRPCPacket(
RpcMessage.SkeletonResetAllRequest,
new SkeletonResetAllRequestT()
);
};
useEffect(() => {
localStorage.setItem('ratioMode', ratio.toString());
}, [ratio]);
useEffect(() => {
onPageOpened();
}, []);
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative">
<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 max-w-5xl justify-center">
<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 max-w-2xl gap-3 items-center">
<div className="flex flex-col w-full xs:max-w-2xl gap-3 items-center">
<div className="flex flex-col">
<Typography variant="main-title">
{l10n.getString('onboarding-manual_proportions-title')}
@@ -73,7 +94,13 @@ export function ManualProportionsPage() {
name="precise"
variant="toggle"
></CheckBox>
{isMobile && (
<div className="flex gap-3 justify-between">
<ButtonsControl></ButtonsControl>
</div>
)}
</div>
<BodyProportions
precise={precise}
type={ratio ? 'ratio' : 'linear'}
@@ -84,31 +111,11 @@ export function ManualProportionsPage() {
<PersonFrontIcon width={200}></PersonFrontIcon>
</div>
</div>
<div className="flex gap-3 mt-5">
<Button
variant="secondary"
state={{ alonePage: state.alonePage }}
to="/onboarding/body-proportions/choose"
>
{l10n.getString('onboarding-previous_step')}
</Button>
<Button variant="secondary" onClick={resetAll}>
{l10n.getString('reset-reset_all')}
</Button>
{!state.alonePage && (
<Button
variant="primary"
className="ml-auto"
to="/onboarding/done"
>
{l10n.getString('onboarding-continue')}
</Button>
)}
</div>
</div>
<div className="w-full py-4 flex flex-row">
<div className="flex flex-grow gap-3"></div>
<div className="flex gap-3"></div>
{!isMobile && (
<div className="flex gap-3 mt-5 mx-4">
<ButtonsControl></ButtonsControl>
</div>
)}
</div>
</div>
<SkipSetupWarningModal

View File

@@ -6,129 +6,189 @@ import { SkipSetupButton } from '../../SkipSetupButton';
import classNames from 'classnames';
import { Typography } from '../../../commons/Typography';
import { Button } from '../../../commons/Button';
import {
SkeletonConfigResponseT,
RpcMessage,
SkeletonConfigRequestT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import saveAs from 'file-saver';
import { save } from '@tauri-apps/api/dialog';
import { writeTextFile } from '@tauri-apps/api/fs';
import { useIsTauri } from '../../../../hooks/breakpoint';
export function ProportionsChoose() {
const isTauri = useIsTauri();
const { l10n } = useLocalization();
const { applyProgress, skipSetup, state } = useOnboarding();
const [skipWarning, setSkipWarning] = useState(false);
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [animated, setAnimated] = useState(false);
applyProgress(0.65);
useRPCPacket(
RpcMessage.SkeletonConfigResponse,
(data: SkeletonConfigResponseT) => {
const blob = new Blob([JSON.stringify(data)], {
type: 'application/json',
});
if (isTauri) {
save({
filters: [
{
name: l10n.getString('onboarding-choose_proportions-file_type'),
extensions: ['json'],
},
],
defaultPath: 'body-proportions.json',
})
.then((path) =>
path ? writeTextFile(path, JSON.stringify(data)) : undefined
)
.catch((err) => {
console.error(err);
});
} else {
saveAs(blob, 'body-proportions.json');
}
}
);
applyProgress(0.85);
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full justify-center relative">
<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">
<div className="w-[666px]">
<Typography variant="main-title">
{l10n.getString('onboarding-choose_proportions')}
<Typography variant="main-title">
{l10n.getString('onboarding-choose_proportions')}
</Typography>
<div className="xs:w-10/12 xs:max-w-[666px]">
<Typography
variant="standard"
color="secondary"
whitespace="whitespace-pre-line"
>
{l10n.getString('onboarding-choose_proportions-description')}
</Typography>
</div>
<div className={classNames('h-full w-[760px] min-w-[760px]')}>
<div className="flex flex-row gap-4 [&>div]:grow">
<div
className={classNames(
'rounded-lg p-4 flex flex-row',
!state.alonePage && 'bg-background-70',
state.alonePage && 'bg-background-60'
)}
>
<div className="flex flex-col gap-4">
<div className="flex flex-grow flex-col gap-4 max-w-sm">
<div>
<Typography variant="main-title" bold>
{l10n.getString(
'onboarding-choose_proportions-manual_proportions'
)}
</Typography>
<Typography variant="vr-accessible" italic>
{l10n.getString(
'onboarding-choose_proportions-manual_proportions-subtitle'
)}
</Typography>
</div>
<div>
<Typography color="secondary">
{l10n.getString(
'onboarding-choose_proportions-manual_proportions-description'
)}
</Typography>
</div>
<div
className={classNames(
'grid xs:grid-cols-2 w-full xs:flex-row mobile:flex-col gap-4 [&>div]:grow'
)}
>
<div
className={classNames(
'rounded-lg p-4 flex flex-row flex-grow',
!state.alonePage && 'bg-background-70',
state.alonePage && 'bg-background-60'
)}
>
<div className="flex flex-col gap-4">
<div className="flex flex-grow flex-col gap-4 max-w-sm">
<div>
<Typography variant="main-title" bold>
{l10n.getString(
'onboarding-choose_proportions-manual_proportions'
)}
</Typography>
<Typography variant="vr-accessible" italic>
{l10n.getString(
'onboarding-choose_proportions-manual_proportions-subtitle'
)}
</Typography>
</div>
<div>
<Typography color="secondary">
{l10n.getString(
'onboarding-choose_proportions-manual_proportions-description'
)}
</Typography>
</div>
</div>
<Button
variant={!state.alonePage ? 'secondary' : 'tiertiary'}
to="/onboarding/body-proportions/manual"
className="self-start mt-auto"
state={{ alonePage: state.alonePage }}
>
{l10n.getString('onboarding-automatic_proportions-manual')}
</Button>
</div>
<Button
variant={!state.alonePage ? 'secondary' : 'tertiary'}
to="/onboarding/body-proportions/manual"
className="self-start mt-auto"
state={{ alonePage: state.alonePage }}
>
{l10n.getString('onboarding-automatic_proportions-manual')}
</Button>
</div>
<div
className={classNames(
'rounded-lg p-4 flex flex-row relative',
!state.alonePage && 'bg-background-70',
state.alonePage && 'bg-background-60'
)}
>
<div className="flex flex-col gap-4">
<div className="flex flex-grow flex-col gap-4 max-w-sm">
<div>
<img
onMouseEnter={() => setAnimated(() => true)}
onAnimationEnd={() => setAnimated(() => false)}
src="/images/slimetower.png"
className={classNames(
'absolute w-1/3 -right-2 -top-32',
animated && 'animate-[bounce_1s_1]'
)}
></img>
<Typography variant="main-title" bold>
{l10n.getString(
'onboarding-choose_proportions-auto_proportions'
)}
</Typography>
<Typography variant="vr-accessible" italic>
{l10n.getString(
'onboarding-choose_proportions-auto_proportions-subtitle'
)}
</Typography>
</div>
<div>
<Typography color="secondary">
{l10n.getString(
'onboarding-choose_proportions-auto_proportions-description'
)}
</Typography>
</div>
</div>
<div
className={classNames(
'rounded-lg p-4 flex flex-row relative',
!state.alonePage && 'bg-background-70',
state.alonePage && 'bg-background-60'
)}
>
<div className="flex flex-col gap-4">
<div className="flex flex-grow flex-col gap-4 max-w-sm">
<img
onMouseEnter={() => setAnimated(() => true)}
onAnimationEnd={() => setAnimated(() => false)}
src="/images/slimetower.png"
className={classNames(
'absolute w-[100px] -right-2 -top-24',
animated && 'animate-[bounce_1s_1]'
)}
></img>
<div>
<Typography variant="main-title" bold>
{l10n.getString(
'onboarding-choose_proportions-auto_proportions'
)}
</Typography>
<Typography variant="vr-accessible" italic>
{l10n.getString(
'onboarding-choose_proportions-auto_proportions-subtitle'
)}
</Typography>
</div>
<div>
<Typography color="secondary">
{l10n.getString(
'onboarding-choose_proportions-auto_proportions-description'
)}
</Typography>
</div>
<Button
variant="primary"
to="/onboarding/body-proportions/auto"
className="self-start mt-auto"
state={{ alonePage: state.alonePage }}
>
{l10n.getString('onboarding-manual_proportions-auto')}
</Button>
</div>
<Button
variant="primary"
to="/onboarding/body-proportions/auto"
className="self-start mt-auto"
state={{ alonePage: state.alonePage }}
>
{l10n.getString('onboarding-manual_proportions-auto')}
</Button>
</div>
</div>
</div>
{!state.alonePage && (
<div className="flex flex-row">
{!state.alonePage && (
<Button variant="secondary" to="/onboarding/reset-tutorial">
{l10n.getString('onboarding-previous_step')}
</Button>
)}
<Button
variant="secondary"
className="self-start ml-4"
to="/onboarding/reset-tutorial"
variant={!state.alonePage ? 'secondary' : 'tertiary'}
className="ml-auto"
onClick={() =>
sendRPCPacket(
RpcMessage.SkeletonConfigRequest,
new SkeletonConfigRequestT()
)
}
>
{l10n.getString('onboarding-previous_step')}
{l10n.getString('onboarding-choose_proportions-save')}
</Button>
)}
</div>
</div>
</div>
<SkipSetupWarningModal

View File

@@ -1,3 +1,4 @@
import { useBreakpoint } from '../../../../../hooks/breakpoint';
import { useTrackers } from '../../../../../hooks/tracker';
import { BodyDisplay } from '../../../../commons/BodyDisplay';
import { Button } from '../../../../commons/Button';
@@ -12,6 +13,7 @@ export function PutTrackersOnStep({
nextStep: () => void;
variant: 'alone' | 'onboarding';
}) {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { trackers } = useTrackers();
@@ -36,10 +38,22 @@ export function PutTrackersOnStep({
</div>
</div>
{isMobile && (
<div className="flex flex-col pt-1 items-center fill-background-50 justify-center px-16">
<BodyDisplay
trackers={trackers}
width={120}
dotsSize={15}
variant="dots"
hideUnassigned={true}
/>
</div>
)}
<div className="flex flex-col gap-3">
<div className="flex gap-3">
<div className="flex gap-3 mobile:justify-between">
<Button
variant={variant === 'onboarding' ? 'secondary' : 'tiertiary'}
variant={variant === 'onboarding' ? 'secondary' : 'tertiary'}
to="/onboarding/body-proportions/choose"
state={{ alonePage: variant === 'alone' }}
>
@@ -53,15 +67,17 @@ export function PutTrackersOnStep({
</div>
</div>
</div>
<div className="flex flex-col pt-1 items-center fill-background-50 justify-center px-16">
<BodyDisplay
trackers={trackers}
width={150}
dotsSize={15}
variant="dots"
hideUnassigned={true}
/>
</div>
{!isMobile && (
<div className="flex flex-col pt-1 items-center fill-background-50 justify-center px-16">
<BodyDisplay
trackers={trackers}
width={150}
dotsSize={15}
variant="dots"
hideUnassigned={true}
/>
</div>
)}
</>
);
}

View File

@@ -35,7 +35,7 @@ export function Recording({ nextStep }: { nextStep: () => void }) {
)}
</Typography>
</div>
<ol className="list-decimal">
<ol className="list-decimal mobile:px-4">
<>
{l10n
.getString('onboarding-automatic_proportions-recording-steps')

View File

@@ -22,7 +22,7 @@ export function RequirementsStep({
'onboarding-automatic_proportions-requirements-title'
)}
</Typography>
<ul className="list-disc">
<ul className="list-disc mobile:px-4">
<>
{l10n
.getString(
@@ -38,9 +38,9 @@ export function RequirementsStep({
</ul>
</div>
<div className="flex gap-3">
<div className="flex gap-3 mobile:justify-between">
<Button
variant={variant === 'onboarding' ? 'secondary' : 'tiertiary'}
variant={variant === 'onboarding' ? 'secondary' : 'tertiary'}
onClick={prevStep}
>
{l10n.getString('onboarding-automatic_proportions-prev_step')}

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