Compare commits

...

27 Commits

Author SHA1 Message Date
Erimel
12b5461849 New Pontoon translations (#839) 2023-09-21 21:50:22 -04:00
Meow Wei
9b43f77c31 Pontoon: Update Traditional Chinese (zh-Hant) localization of GUI
Co-authored-by: Meow Wei <medicalwei@gmail.com>
2023-09-21 22:40:19 -03:00
Disappear9
d3fab10ea7 Pontoon: Update Simplified Chinese (zh-Hans) localization of GUI
Co-authored-by: Disappear9 <disappear9@outlook.com>
2023-09-21 22:40:19 -03:00
ReCluyem
de51497cee Pontoon: Update Russian (ru) localization of GUI
Co-authored-by: ReCluyem <dim.golovaha@yandex.ru>
2023-09-21 22:40:19 -03:00
ReDoX
a19de94130 Pontoon: Update Polish (pl) localization of GUI
Co-authored-by: ReDoX <redox01@o2.pl>
2023-09-21 22:40:19 -03:00
Smeltie
e11b80c8e0 Pontoon: Update Dutch (nl) localization of GUI
Co-authored-by: Smeltie <martijnklerks123@gmail.com>
2023-09-21 22:40:11 -03:00
Erimel
9b3f9eccab Pontoon: Update French (fr) localization of GUI
Co-authored-by: Erimel <loukalemire@gmail.com>
2023-09-21 16:42:56 +00:00
namakeingo
3752a11f84 Pontoon: Update Italian (it) localization of GUI
Co-authored-by: namakeingo <namakeingo@gmail.com>
2023-09-21 16:42:56 +00:00
FennT
7c89185a40 Pontoon: Update Arabic (ar) localization of GUI
Co-authored-by: FennT <0094falcon@gmail.com>
2023-09-21 16:42:56 +00:00
MarcoM
4284e1f52c feat: use path-alias (#771) 2023-09-21 12:42:29 -04:00
Uriel
7a37773441 Fix RPCUtil not checking for the interface before looking for it (#849) 2023-09-20 02:27:29 -04:00
Erimel
4dc8ce979d Add _trackerNum to extensions' displaynames (#848)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-09-19 19:27:10 -04:00
Erimel
6a30da671d Filter out !isSiteLocalAddress from addresses (#847)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-09-17 21:23:37 -04:00
Butterscotch!
3f307605cc Android ByteBuffer and Color fixes (#842) 2023-09-15 22:37:46 -04:00
Erimel
185dc8d674 Fix foot tracker orientation (#843) 2023-09-14 19:46:47 +03:00
Erimel
55d6a01a4c Fix hash diplayName to not change (#841) 2023-09-14 19:46:11 +03:00
Louka Lemire
34f357572a Fix right foot skeleton offset (#840) 2023-09-03 19:09:52 -04:00
Uriel
1aaf01f2ca use devenv for nix develop (#830) 2023-09-03 02:25:56 +03:00
Erimel
bc5f9a17c4 Resets settings (#806) 2023-09-03 02:25:21 +03:00
Kitlith
7231f46804 Track connection by SocketAddress instead of IP address. (#753) 2023-09-03 01:12:55 +03:00
Butterscotch!
b467af8c46 Fix icons and add more & fill in web manifest (#835) 2023-09-03 01:12:06 +03:00
Erimel
4393a6f137 knee-ankle interpolation (#780)
Co-authored-by: Uriel <urielfontan2002@gmail.com>
2023-09-03 01:11:28 +03:00
Uriel
5d773a37ab Fix config shenanigans (#836) 2023-09-02 16:14:41 -04:00
Erimel
17306c1976 Make UDPPackets Floats safe (#832) 2023-09-02 16:02:02 -04:00
Uriel
6dfc8a8101 add import proportions button (#811) 2023-09-02 15:57:00 -04:00
Erimel
ac5a68d33d Convert HumanSkeleton to Kotlin (#783) 2023-08-31 19:19:45 -04:00
Uriel
f2d663c341 Update metainfo (#834) 2023-08-31 22:25:14 +03:00
141 changed files with 3575 additions and 2912 deletions

11
.envrc
View File

@@ -1 +1,10 @@
use flake
if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs="
fi
nix_direnv_watch_file rust-toolchain.toml
nix_direnv_watch_file package.json
if ! use flake . --impure
then
echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2
fi

1
.gitignore vendored
View File

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

464
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,3 +19,4 @@ strip = "debuginfo" # Only affects Unix binaries with DWARF
[patch.crates-io]
tauri = { git = "https://github.com/imurx/tauri", branch = "ipc-backport" }
tauri-runtime = { git = "https://github.com/imurx/tauri", branch = "ipc-backport" }
tauri-build = { git = "https://github.com/imurx/tauri", branch = "ipc-backport" }

View File

@@ -48,7 +48,6 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
tracking (FBT) in virtual reality. With no base station required, SlimeVR makes wireless
VR FBT affordable and comfortable.
</p>
</description>
<launchable type="desktop-id">dev.slimevr.SlimeVR.desktop</launchable>
@@ -59,6 +58,14 @@ work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
</screenshot>
</screenshots>
<releases>
<release version="0.9.1" date="2023-08-30"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.1</url></release>
<release version="0.9.1-rc.4" type="development" date="2023-08-28"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.1-rc.4</url></release>
<release version="0.9.1-rc.3" type="development" date="2023-08-19"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.1-rc.3</url></release>
<release version="0.9.1-rc.2" type="development" date="2023-08-15"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.1-rc.2</url></release>
<release version="0.9.1-rc.1" type="development" date="2023-08-13"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.1-rc.1</url></release>
<release version="0.9.0" date="2023-08-05"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.0</url></release>
<release version="0.9.0-rc.2" type="development" date="2023-08-02"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.0-rc.2</url></release>
<release version="0.9.0-rc.1" type="development" date="2023-07-31"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.9.0-rc.1</url></release>
<release version="0.8.3" date="2023-07-09"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.3</url></release>
<release version="0.8.2" date="2023-07-09"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.2</url></release>
<release version="0.8.2-rc.1" type="development" date="2023-07-07"><url>https://github.com/SlimeVR/SlimeVR-Server/releases/tag/v0.8.2-rc.1</url></release>

318
flake.lock generated
View File

@@ -1,15 +1,69 @@
{
"nodes": {
"devenv": {
"inputs": {
"flake-compat": "flake-compat",
"nix": "nix",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1692203620,
"narHash": "sha256-9SF/H8oCWv166q5o+JtV7tK+koydgFMu02HCB27UWpU=",
"owner": "cachix",
"repo": "devenv",
"rev": "eee80243720b7f284128873a9694a520d9967b2f",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1690933134,
"narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb",
"type": "github"
},
"original": {
"id": "flake-parts",
"type": "indirect"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
@@ -19,15 +73,12 @@
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
@@ -36,28 +87,111 @@
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"devenv",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"lowdown-src": {
"flake": false,
"locked": {
"lastModified": 1633514407,
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
"owner": "kristapsdz",
"repo": "lowdown",
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
"type": "github"
},
"original": {
"owner": "kristapsdz",
"repo": "lowdown",
"type": "github"
}
},
"mk-shell-bin": {
"locked": {
"lastModified": 1677004959,
"narHash": "sha256-/uEkr1UkJrh11vD02aqufCxtbF5YnhRTIKlx5kyvf+I=",
"owner": "rrbutani",
"repo": "nix-mk-shell-bin",
"rev": "ff5d8bd4d68a347be5042e2f16caee391cd75887",
"type": "github"
},
"original": {
"owner": "rrbutani",
"repo": "nix-mk-shell-bin",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
"nixpkgs": [
"devenv",
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1676545802,
"narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
"owner": "domenkozar",
"repo": "nix",
"rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "relaxed-flakes",
"repo": "nix",
"type": "github"
}
},
"nix2container": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1688922987,
"narHash": "sha256-RnQwrCD5anqWfyDAVbfFIeU+Ha6cwt5QcIwIkaGRzQw=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "ab381a7d714ebf96a83882264245dbd34f0a7ec8",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1691654369,
"narHash": "sha256-gSILTEx1jRaJjwZxRlnu3ZwMn1FVNk80qlwiCX8kmpo=",
"lastModified": 1678875422,
"narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ce5e4a6ef2e59d89a971bc434ca8ca222b9c7f5e",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1681358109,
"narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9",
"rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
"type": "github"
},
"original": {
@@ -67,32 +201,109 @@
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2"
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1691892594,
"narHash": "sha256-Lt9/WUnI/ZqBYnHOC3n6Lg5jTfd/ZI+39jZx5HmolSQ=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "c638e10caf94caaa97fb1df74e3bb467dc9b92db",
"dir": "lib",
"lastModified": 1690881714,
"narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9e1960bc196baf6881340d53dccb203a951745a2",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1685801374,
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1692356644,
"narHash": "sha256-AYkPFT+CbCVSBmh0WwIzPpwhEJ4Yy3A7JZvUkGJIg5o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8ecc900b2f695d74dea35a92f8a9f9b32c8ea33d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": [
"devenv",
"flake-compat"
],
"flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": [
"devenv",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1688056373,
"narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"flake-parts": "flake-parts",
"mk-shell-bin": "mk-shell-bin",
"nix2container": "nix2container",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
@@ -107,21 +318,6 @@
"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",

172
flake.nix
View File

@@ -1,87 +1,109 @@
{
description = "Server app for SlimeVR ecosystem";
description = "Affordable full-body tracking for VR!";
inputs.nixpkgs.url = "nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
devenv.url = "github:cachix/devenv";
nix2container.url = "github:nlewo/nix2container";
nix2container.inputs.nixpkgs.follows = "nixpkgs";
mk-shell-bin.url = "github:rrbutani/nix-mk-shell-bin";
};
inputs.rust-overlay.url = "github:oxalica/rust-overlay";
nixConfig = {
extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
extra-substituters = "https://devenv.cachix.org";
};
outputs = {
self,
nixpkgs,
flake-utils,
rust-overlay,
}:
flake-utils.lib.eachDefaultSystem
(
system: let
overlays = [(import rust-overlay)];
pkgs = import nixpkgs {
inherit system overlays;
};
rustTarget = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
nativeBuildInputs = with pkgs; [
curl
gcc
openssl
pkgconfig
which
zlib
outputs = inputs @ {flake-parts, ...}:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.devenv.flakeModule
];
systems = ["x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin"];
freetype
expat
];
buildInputs = with pkgs; [
appimagekit
atk
cairo
dbus
dbus.lib
dprint
gdk-pixbuf
glib.out
gobject-introspection
gtk3
harfbuzz
libffi
libsoup_3
openssl.out
pango
pkg-config
treefmt
webkitgtk_4_1
zlib
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
librsvg
perSystem = {
config,
self',
inputs',
pkgs,
system,
lib,
...
}: {
# Per-system attributes can be defined here. The self' and inputs'
# module parameters provide easy access to attributes of the same
# system.
# Some nice things to have
exa
fd
# Equivalent to inputs'.nixpkgs.legacyPackages.hello;
# packages.default = pkgs.hello;
jdk17 # JDK17
nodejs
gradle
];
in {
devShells.default = pkgs.mkShell {
nativeBuildInputs =
nativeBuildInputs
++ [
];
buildInputs =
buildInputs
++ [
rustTarget
devenv.shells.default = {
name = "slimevr";
imports = [
# This is just like the imports in devenv.nix.
# See https://devenv.sh/guides/using-with-flake-parts/#import-a-devenv-module
# ./devenv-foo.nix
];
# https://devenv.sh/reference/options/
packages =
[
]
++ lib.optionals pkgs.stdenv.isLinux (with pkgs; [
appimagekit
atk
cairo
dbus
dbus.lib
dprint
gdk-pixbuf
glib.out
gobject-introspection
gtk3
harfbuzz
libffi
libsoup_3
openssl.out
pango
pkg-config
treefmt
webkitgtk_4_1
zlib
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
librsvg
freetype
expat
])
++ lib.optionals pkgs.stdenv.isDarwin [
pkgs.darwin.apple_sdk.frameworks.Security
];
shellHook = ''
alias ls=exa
alias find=fd
languages.java = {
enable = true;
gradle.enable = true;
jdk.package = pkgs.jdk17;
};
languages.kotlin.enable = true;
languages.javascript = {
enable = true;
corepack.enable = true;
};
languages.rust.enable = true;
enterShell = with pkgs; ''
'';
};
}
);
};
flake = {
# The usual flake attributes can be defined here, including system-
# agnostic ones like nixosModule and system-enumerating ones, although
# those are more easily expressed in perSystem.
};
};
}

View File

@@ -4,7 +4,7 @@
"es2021": true,
"jest": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:@dword-design/import-alias/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
@@ -30,6 +30,14 @@
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"@dword-design/import-alias/prefer-alias": [
"error",
{
"alias": {
"@": "./src/"
}
}
]
},
"settings": {

View File

@@ -1,5 +1,5 @@
export default {
"**/*.{ts,tsx}": () => "tsc -p tsconfig.json --noEmit",
"**/*.{js,jsx,ts,tsx}": "eslint --cache --fix",
"**/*.{js,jsx,ts,tsx}": "eslint --max-warnings=0 --cache --fix",
"**/*.{js,jsx,ts,tsx,css,md,json}": "prettier --write"
};

View File

@@ -16,10 +16,10 @@
"@tauri-apps/plugin-shell": "github:tauri-apps/tauri-plugin-shell#v2",
"@tauri-apps/plugin-window": "github:tauri-apps/tauri-plugin-window#v2",
"@vitejs/plugin-react": "^3.0.0",
"browser-fs-access": "^0.34.1",
"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",
@@ -71,6 +71,7 @@
]
},
"devDependencies": {
"@dword-design/eslint-plugin-import-alias": "^4.0.8",
"@tailwindcss/forms": "^0.5.3",
"@tauri-apps/cli": "^2.0.0-alpha.10",
"@types/file-saver": "^2.0.5",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -348,9 +348,20 @@ 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-leg_fk-reset_mounting_feet-description = تمكين إعادة ضبط تركيب القدمين عن طريق المشي على رؤوس الأصابع.
settings-general-fk_settings-leg_fk-reset_mounting_feet = إعادة تعيين تركيب القدمين
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-reset_mode-description = قم بتغيير وضع الذراع المتوقع لإعادة ضبط المتصاعد.
settings-general-fk_settings-arm_fk-back = العودة
settings-general-fk_settings-arm_fk-back-description = الوضع الافتراضي، مع وضع الذراعين العلويين إلى الخلف والساعدين للأمام.
settings-general-fk_settings-arm_fk-tpose_up = تي بوز (أعلى)
settings-general-fk_settings-arm_fk-tpose_up-description = يتوقع أن تكون ذراعيك لأسفل على الجانبين أثناء إعادة الضبط الكامل ، و 90 درجة حتى الجانبين أثناء إعادة ضبط التركيب.
settings-general-fk_settings-arm_fk-tpose_down = تي بوز (لأسفل)
settings-general-fk_settings-arm_fk-tpose_down-description = يتوقع أن تكون ذراعيك 90 درجة لأعلى على الجانبين أثناء إعادة الضبط الكامل ، ولأسفل على الجانبين أثناء إعادة ضبط التركيب.
settings-general-fk_settings-arm_fk-forward = أمامي
settings-general-fk_settings-arm_fk-forward-description = يتوقع أن تكون ذراعيك 90 درجة للأمام. مفيد ل VTubing.
settings-general-fk_settings-skeleton_settings-toggles = تبديل الهيكل العظمي
settings-general-fk_settings-skeleton_settings-description = تبديل إعدادات الهيكل العظمي أو إيقافه. يوصى بتركها شغالة.
settings-general-fk_settings-skeleton_settings-extended_spine_model = نموذج العمود الفقري الممتد
@@ -364,6 +375,7 @@ settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = خص
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = خصص الورك من الخصر إلى الساقين
settings-general-fk_settings-skeleton_settings-interp_hip_legs = متوسط انعراج الفخذ وتدحرج مع الساقين'
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = متوسط الانحراف وتدحرج مع الكاحلين
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = متوسط انحراف الركبتين ولفة مع الكاحلين
settings-general-fk_settings-self_localization-title = وضع Mocap
settings-general-fk_settings-self_localization-description = يسمح وضع Mocap للهيكل العظمي بتعقب موضعه تقريبا بدون سماعة رأس أو أجهزة تعقب أخرى. لاحظ أن هذا يتطلب أجهزة تعقب القدمين والرأس للعمل ولا تزال تجريبية.
settings-general-fk_settings-vive_emulation-title = محاكاة فايف
@@ -825,6 +837,9 @@ onboarding-choose_proportions-manual_proportions = النسب اليدوية
onboarding-choose_proportions-manual_proportions-subtitle = للمسات الصغيرة
onboarding-choose_proportions-manual_proportions-description = سيسمح لك بتعديل النسب يدويًا عن طريق تعديلها مباشرة
onboarding-choose_proportions-export = تصدير النسب
onboarding-choose_proportions-import = استيراد النسب
onboarding-choose_proportions-import-success = تم استيراده
onboarding-choose_proportions-import-failed = فشل
onboarding-choose_proportions-file_type = ملف نسب الجسم
## Tracker manual proportions setup

View File

@@ -322,9 +322,20 @@ settings-general-fk_settings-leg_tweak-floor_clip-description = Floor-clip can R
settings-general-fk_settings-leg_tweak-toe_snap-description = Toe-snap attempts to guess the rotation of your feet if feet trackers are not in use.
settings-general-fk_settings-leg_tweak-foot_plant-description = Foot-plant rotates your feet to be parallel to the ground when in contact.
settings-general-fk_settings-leg_fk = Leg tracking
settings-general-fk_settings-leg_fk-reset_mounting_feet-description = Enable feet Mounting Reset by tiptoeing.
settings-general-fk_settings-leg_fk-reset_mounting_feet = Feet Mounting Reset
settings-general-fk_settings-arm_fk = Arm tracking
settings-general-fk_settings-arm_fk-description = Force arms to be tracked from the HMD even if positional hand data is available.
settings-general-fk_settings-arm_fk-force_arms = Force arms from HMD
settings-general-fk_settings-arm_fk-reset_mode-description = Change which arm pose is expected for mounting reset.
settings-general-fk_settings-arm_fk-back = Back
settings-general-fk_settings-arm_fk-back-description = The default mode, with the upper arms going back and lower arms going forward.
settings-general-fk_settings-arm_fk-tpose_up = T-pose (up)
settings-general-fk_settings-arm_fk-tpose_up-description = Expects your arms to be down on the sides during Full Reset, and 90 degrees up to the sides during Mounting Reset.
settings-general-fk_settings-arm_fk-tpose_down = T-pose (down)
settings-general-fk_settings-arm_fk-tpose_down-description = Expects your arms to be 90 degrees up to the sides during Full Reset, and down on the sides during Mounting Reset.
settings-general-fk_settings-arm_fk-forward = Forward
settings-general-fk_settings-arm_fk-forward-description = Expects your arms to be up 90 degrees forward. Useful for VTubing.
settings-general-fk_settings-skeleton_settings-toggles = Skeleton toggles
settings-general-fk_settings-skeleton_settings-description = Toggle skeleton settings on or off. It is recommended to leave these on.
settings-general-fk_settings-skeleton_settings-extended_spine_model = Extended spine model
@@ -338,6 +349,7 @@ settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = Impu
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Impute hip from waist to legs
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Average the hip's yaw and roll with the legs'
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Average the knee trackers' yaw and roll with the ankles'
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = Average the knees' yaw and roll with the ankles'
settings-general-fk_settings-self_localization-title = Mocap mode
settings-general-fk_settings-self_localization-description = Mocap Mode allows the skeleton to roughly track its own position without a headset or other trackers. Note that this requires feet and head trackers to work and is still experimental.
@@ -747,6 +759,9 @@ onboarding-choose_proportions-manual_proportions = Manual proportions
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-export = Export proportions
onboarding-choose_proportions-import = Import proportions
onboarding-choose_proportions-import-success = Imported
onboarding-choose_proportions-import-failed = Failed
onboarding-choose_proportions-file_type = Body proportions file
## Tracker manual proportions setup

View File

@@ -348,9 +348,20 @@ settings-general-fk_settings-leg_tweak-floor_clip-description = Le limitage au s
settings-general-fk_settings-leg_tweak-toe_snap-description = La correction des orteils estime l'orientation de vos pieds si vous ne portez pas de capteurs sur ses derniers.
settings-general-fk_settings-leg_tweak-foot_plant-description = La correction des pieds oriente vos pieds pour qu'ils soient parallèles au sol lorsqu'ils le touche.
settings-general-fk_settings-leg_fk = Capture des jambes
settings-general-fk_settings-leg_fk-reset_mounting_feet-description = Activer la réinitialisation de l'alignement des pieds en allant sur la pointe des pieds.
settings-general-fk_settings-leg_fk-reset_mounting_feet = Réinitialisation de l'alignement des pieds
settings-general-fk_settings-arm_fk = Capture des bras
settings-general-fk_settings-arm_fk-description = Changez la façon dont les bras sont captés.
settings-general-fk_settings-arm_fk-force_arms = Forcer les bras en provenance du casque VR
settings-general-fk_settings-arm_fk-reset_mode-description = Changer la pose des bras attendue pour la réinitialisation de l'alignement.
settings-general-fk_settings-arm_fk-back = En arrière
settings-general-fk_settings-arm_fk-back-description = Le mode par défaut, avec les bras vers larrière et les avant-bras vers lavant.
settings-general-fk_settings-arm_fk-tpose_up = T-pose (vers le haut)
settings-general-fk_settings-arm_fk-tpose_up-description = Sattend à ce que vos bras soient vers le bas sur les côtés pendant la réinitialisation complète et à 90 degrés vers l'extérieur pendant la réinitialisation de l'alignement.
settings-general-fk_settings-arm_fk-tpose_down = T-pose (vers le bas)
settings-general-fk_settings-arm_fk-tpose_down-description = Sattend à ce que vos bras soient à 90 degrés vers l'extérieur pendant la réinitialisation complète et vers le bas sur les côtés pendant la réinitialisation de l'alignement.
settings-general-fk_settings-arm_fk-forward = En avant
settings-general-fk_settings-arm_fk-forward-description = Sattend à ce que vos bras soient levés 90 degrés vers lavant. Utile pour le VTubing.
settings-general-fk_settings-skeleton_settings-toggles = Bascules du squelette
settings-general-fk_settings-skeleton_settings-description = Activez ou désactivez des paramètres avancés de capture.
settings-general-fk_settings-skeleton_settings-extended_spine_model = Modèle de colonne vertébrale avancé
@@ -364,6 +375,7 @@ settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = Inte
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Interpoler la hanche de la taille aux jambes
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Interpoler la rotation horizontale et de torsion de la hanche avec celle des jambes
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Interpoler les rotations horizontales et de torsion des capteurs de genoux avec celles des chevilles
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = Interpoler les rotations horizontales et de torsion des genoux avec celles des chevilles
settings-general-fk_settings-self_localization-title = Mode Mocap
settings-general-fk_settings-self_localization-description = Le mode Mocap permet au squelette de suivre grossièrement sa propre position sans casque ou autres capteurs. Ce mode nécessite des capteurs de pieds et de tête afin de fonctionner et est encore expérimental.
settings-general-fk_settings-vive_emulation-title = Émulation Vive
@@ -809,6 +821,9 @@ onboarding-choose_proportions-manual_proportions = Proportions manuelles
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-export = Exporter les proportions
onboarding-choose_proportions-import = Importer les proportions
onboarding-choose_proportions-import-success = Importé
onboarding-choose_proportions-import-failed = Raté
onboarding-choose_proportions-file_type = Fichier de proportions
## Tracker manual proportions setup

View File

@@ -346,9 +346,20 @@ settings-general-fk_settings-leg_tweak-floor_clip-description = "Compenetrazione
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.
settings-general-fk_settings-leg_tweak-foot_plant-description = "Piedi piantati" ruota i piedi in modo tale che siano paralleli al terreno quando in contatto con esso.
settings-general-fk_settings-leg_fk = Tracking delle gambe
settings-general-fk_settings-leg_fk-reset_mounting_feet-description = Abilita Reset posizionamento dei piedi mettendosi in punta di piedi.
settings-general-fk_settings-leg_fk-reset_mounting_feet = Reset posizionamento dei piedi
settings-general-fk_settings-arm_fk = Tracking delle braccia
settings-general-fk_settings-arm_fk-description = Cambia la modalità di tracking delle braccia.
settings-general-fk_settings-arm_fk-force_arms = Forza il calcolo della posizione delle braccia a utilizzare il HMD
settings-general-fk_settings-arm_fk-reset_mode-description = Cambia la posa delle braccia usata per il reset posizionamento.
settings-general-fk_settings-arm_fk-back = Indietro
settings-general-fk_settings-arm_fk-back-description = La modalità predefinita, con la parte superiori delle braccia che vanno indietro e le parte inferiori delle braccia che vanno avanti.
settings-general-fk_settings-arm_fk-tpose_up = Posa a T (in alto)
settings-general-fk_settings-arm_fk-tpose_up-description = Si aspetta che le braccia siano abbassate sui lati durante il Reset Completo e a 90 gradi con il busto ai lati per il Reset Posizionamento.
settings-general-fk_settings-arm_fk-tpose_down = Posa a T (in basso)
settings-general-fk_settings-arm_fk-tpose_down-description = Si aspetta che le braccia siano a 90 gradi con il busto ai lati durante il Reset Completo e abbassate sui lati per il Reset Posizionamento.
settings-general-fk_settings-arm_fk-forward = Avanti
settings-general-fk_settings-arm_fk-forward-description = Si aspetta che le tue braccia siano alzate di 90 gradi in avanti. Utile per VTubing.
settings-general-fk_settings-skeleton_settings-toggles = Interruttori per lo scheletro
settings-general-fk_settings-skeleton_settings-description = Abilita o disabilita le impostazioni dello scheletro. É raccomandato lasciare queste impostazioni attive.
settings-general-fk_settings-skeleton_settings-extended_spine_model = Modello di colonna vertebrale estesa
@@ -362,6 +373,7 @@ settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = Impu
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Imputazione dei valori del bacino dalla combinazione del girovita e gambe
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Media dell'orientamento del bacino e la rotazione delle gambe
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Media dell'orientamento del ginocchio e la rotazione delle caviglie
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = Media dell'orientamento delle ginocchia e la rotazione delle caviglie
settings-general-fk_settings-self_localization-title = Modalità Mocap
settings-general-fk_settings-self_localization-description = La modalità Mocap consente allo scheletro di tracciare approssimativamente la propria posizione senza visore o altri tracker. Si noti che questo richiede trakers per piedi e la testa per funzionare ed è ancora in fase sperimentale.
settings-general-fk_settings-vive_emulation-title = Imitazione Vive
@@ -808,6 +820,9 @@ onboarding-choose_proportions-manual_proportions = Proporzioni manuali
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.
onboarding-choose_proportions-export = Esporta le proporzioni del corpo
onboarding-choose_proportions-import = Importa le proporzioni del corpo
onboarding-choose_proportions-import-success = Importate con successo
onboarding-choose_proportions-import-failed = Importaggio fallito
onboarding-choose_proportions-file_type = File delle proporzioni del corpo
## Tracker manual proportions setup

View File

@@ -353,6 +353,7 @@ settings-general-fk_settings-leg_fk = Been tracking
settings-general-fk_settings-arm_fk = Arm tracking
settings-general-fk_settings-arm_fk-description = Verander de manier waarop de armen worden getrackt.
settings-general-fk_settings-arm_fk-force_arms = Dwing armen vanuit HMD
settings-general-fk_settings-arm_fk-reset_mode-description = Pas de verwachte armhouding aan voor het resetten van de montage.
settings-general-fk_settings-skeleton_settings-toggles = Skelet schakelaars
settings-general-fk_settings-skeleton_settings-description = Schakel skeleton instellingen in of uit. Het is aanbevolen om deze aan te laten.
settings-general-fk_settings-skeleton_settings-extended_spine_model = Uitgebreid ruggengraat model
@@ -661,8 +662,8 @@ onboarding-assignment_tutorial = Hoe een Slime Tracker voor te bereiden voordat
onboarding-assignment_tutorial-first_step = 1. Plaats een lichaamsdeelsticker (als je die hebt) op de tracker naar keuze
# 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 = Bevestig de riem aan je tracker, waarbij je de haak-en-luskant van het bandje in de volgende richting houdt:
onboarding-assignment_tutorial-second_step-continuation = De haak-en-luskant voor de verlenging moet in deze richting staan:
onboarding-assignment_tutorial-second_step-v2 = Bevestig de strap aan de tracker met de klittenbandzijde in dezelfde richting als de voorzijde van de tracker:
onboarding-assignment_tutorial-second_step-continuation-v2 = De klittenbandzijde van de extensie moet naar boven gericht zijn, zoals in de foto afgebeeld:
onboarding-assignment_tutorial-done = Ik heb stickers en riemen geplaatst!
## Tracker assignment setup
@@ -808,6 +809,9 @@ onboarding-choose_proportions-manual_proportions = Handmatige lichaamsverhouding
onboarding-choose_proportions-manual_proportions-subtitle = Voor kleine details
onboarding-choose_proportions-manual_proportions-description = Hier kan je jouw verhoudingen handmatig aanpassen
onboarding-choose_proportions-export = Export proporties
onboarding-choose_proportions-import = Importeer proporties
onboarding-choose_proportions-import-success = geïmporteerd
onboarding-choose_proportions-import-failed = Mislukt
onboarding-choose_proportions-file_type = Lichaamsproporties bestand
## Tracker manual proportions setup

View File

@@ -348,9 +348,20 @@ settings-general-fk_settings-leg_tweak-floor_clip-description = Floor-clip może
settings-general-fk_settings-leg_tweak-toe_snap-description = Toe-snap próbuje odgadnąć obrót twoich stóp, jeśli trackery stóp nie są używane.
settings-general-fk_settings-leg_tweak-foot_plant-description = Foot-plant obraca stopy, aby były równoległe do podłoża podczas kontaktu.
settings-general-fk_settings-leg_fk = Śledzenie nóg
settings-general-fk_settings-leg_fk-reset_mounting_feet-description = Włącz resetowanie montażu stóp, chodząc na palcach.
settings-general-fk_settings-leg_fk-reset_mounting_feet = Reset mocowania stóp
settings-general-fk_settings-arm_fk = Śledzenie ramienia
settings-general-fk_settings-arm_fk-description = Zmień sposób śledzenia ramion.
settings-general-fk_settings-arm_fk-force_arms = Śledź ramiona z gogli VR
settings-general-fk_settings-arm_fk-reset_mode-description = Zmień pozycję ramienia oczekiwaną przy resetowaniu montażu.
settings-general-fk_settings-arm_fk-back = Wstecz
settings-general-fk_settings-arm_fk-back-description = Tryb domyślny, w którym górne ramiona cofają się, a dolne ramiona przesuwają się do przodu.
settings-general-fk_settings-arm_fk-tpose_up = T-pose (w górę)
settings-general-fk_settings-arm_fk-tpose_up-description = Oczekuje, że podczas pełnego resetu twoje ramiona będą opuszczone na boki w 90 stopni w górę podczas resetu montażowego.
settings-general-fk_settings-arm_fk-tpose_down = T-pose (w dół)
settings-general-fk_settings-arm_fk-tpose_down-description = Oczekuje, że Twoje ramiona będą ustawione pod kątem w 90 stopni na boki podczas Pełnego Resetu i w dół po bokach podczas Resetu Montażowego.
settings-general-fk_settings-arm_fk-forward = Do przodu
settings-general-fk_settings-arm_fk-forward-description = Oczekuje, że Twoje ramiona będą uniesione pod kątem 90 stopni do przodu. Przydatne w VTubingu.
settings-general-fk_settings-skeleton_settings-toggles = Przełączniki szkieletowe
settings-general-fk_settings-skeleton_settings-description = Włącz lub wyłącz ustawienia szkieletu. Zaleca się pozostawienie ich włączonych.
settings-general-fk_settings-skeleton_settings-extended_spine_model = Wydłużony model kręgosłupa
@@ -364,6 +375,7 @@ settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = Przy
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Przypisz biodro od pasa do nóg
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Średnie odchylenie biodra i przetoczenie nogami
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Uśrednij odchylenie i przechylenie nakolanników za pomocą kostek
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = Średnie odchylenie kolan i przechylenie kostek
settings-general-fk_settings-self_localization-title = Tryb Mocap
settings-general-fk_settings-self_localization-description = Tryb Mocap pozwala szkieletowi z grubsza śledzić własną pozycję bez headsetu lub innych trackerów. Pamiętaj, że wymaga to śledzenia stóp i głowy do działania i nadal jest eksperymentalne.
settings-general-fk_settings-vive_emulation-title = Emulacja Vive
@@ -665,6 +677,7 @@ onboarding-assignment_tutorial = Jak przygotować Slime Tracker przed założeni
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-v2 = 2. Przymocuj pasek do trackera, tak aby rzep paska był skierowany w tę samą stronę, co slime face część trackera:
onboarding-assignment_tutorial-second_step-continuation-v2 = Strona z rzepem dla przedłużenia powinna być skierowana do góry, jak na poniższym obrazku:
onboarding-assignment_tutorial-done = Umieszczam naklejki i paski!
@@ -816,6 +829,9 @@ onboarding-choose_proportions-manual_proportions = Ręczne proporcje
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-export = Eksportuj proporcje
onboarding-choose_proportions-import = Importuj proporcje
onboarding-choose_proportions-import-success = Importowane
onboarding-choose_proportions-import-failed = Niepowodzenie
onboarding-choose_proportions-file_type = Proporcje ciała
## Tracker manual proportions setup

View File

@@ -358,6 +358,10 @@ settings-general-fk_settings-skeleton_settings-extended_pelvis_model = Моде
settings-general-fk_settings-skeleton_settings-extended_knees_model = Модель с удлиненным коленом
settings-general-fk_settings-skeleton_settings-ratios = Соотношения скелета
settings-general-fk_settings-skeleton_settings-ratios-description = Измените значения параметров скелета. Возможно, вам придется скорректировать пропорции после их изменения.
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_hip = Рассчитать талию от груди до бёдер
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_legs = Рассчитать талию от груди до ног
settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = Рассчитать бедро от груди до ног
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = Рассчитать бедро от талии до ног
settings-general-fk_settings-skeleton_settings-interp_hip_legs = Усредните рыскание и перекат бедра c рысканьем и перекатом ног
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = Усредните рыскание и крен коленных трекеров с рысканьем и креном трекеров лодыжек
settings-general-fk_settings-self_localization-title = Режим Mocap
@@ -813,6 +817,9 @@ onboarding-choose_proportions-manual_proportions = Ручные пропорци
onboarding-choose_proportions-manual_proportions-subtitle = Для небольших штрихов
onboarding-choose_proportions-manual_proportions-description = Это позволит вам настроить пропорции вручную, изменив их напрямую.
onboarding-choose_proportions-export = Экспорт пропорций
onboarding-choose_proportions-import = Ввод пропорций
onboarding-choose_proportions-import-success = Введён
onboarding-choose_proportions-import-failed = Неудача
onboarding-choose_proportions-file_type = Файл пропорций тела
## Tracker manual proportions setup

View File

@@ -348,9 +348,20 @@ 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-leg_fk-reset_mounting_feet-description = 开启脚部佩戴重置。(佩戴重置时需要踮起脚尖)
settings-general-fk_settings-leg_fk-reset_mounting_feet = 脚部佩戴重置
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-reset_mode-description = 更改佩戴重置时使用的手臂姿势。
settings-general-fk_settings-arm_fk-back = 向后弯折
settings-general-fk_settings-arm_fk-back-description = 默认,重置时大臂向后,小臂向前,类似滑雪。
settings-general-fk_settings-arm_fk-tpose_up = T-pose抬起
settings-general-fk_settings-arm_fk-tpose_up-description = 完整重置时手臂垂下,呈立正姿势;佩戴重置时手臂向两侧伸平。
settings-general-fk_settings-arm_fk-tpose_down = T-pose放下
settings-general-fk_settings-arm_fk-tpose_down-description = 完整重置时手臂向两侧伸平;佩戴重置时手臂垂下,呈立正姿势。
settings-general-fk_settings-arm_fk-forward = 向前伸平
settings-general-fk_settings-arm_fk-forward-description = 重置时手臂向前伸平,有利于坐姿进行虚拟直播。
settings-general-fk_settings-skeleton_settings-toggles = 骨架设置
settings-general-fk_settings-skeleton_settings-description = 打开或关闭骨架设置。建议保持这些设置不变。
settings-general-fk_settings-skeleton_settings-extended_spine_model = 延伸脊柱模型
@@ -363,7 +374,8 @@ settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_legs =
settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = 用胸部到腿部的数据推算髋部
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = 用腰部到腿部的数据推算髋部
settings-general-fk_settings-skeleton_settings-interp_hip_legs = 平均髋部与腿部间航向轴和横滚轴的数值
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = 平均膝盖与小腿间航向轴和横滚轴的数值
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = 平均膝盖追踪器与小腿间航向轴和横滚轴的数值
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = 平均膝盖与小腿间航向轴和横滚轴的数值
settings-general-fk_settings-self_localization-title = 动作捕捉模式
settings-general-fk_settings-self_localization-description = 动作捕捉模式允许在没有头戴设备或其他追踪器的情况下粗略地跟踪骨架姿态。请注意,本功能需要脚部和头部追踪器,且现阶段依然是实验性的。
settings-general-fk_settings-vive_emulation-title = Vive 模拟
@@ -799,6 +811,9 @@ onboarding-choose_proportions-manual_proportions = 手动调整身体比例
onboarding-choose_proportions-manual_proportions-subtitle = 用于精细调整
onboarding-choose_proportions-manual_proportions-description = 这将需要你手动修改以调整你的身体比例
onboarding-choose_proportions-export = 导出身体比例
onboarding-choose_proportions-import = 导入身体比例
onboarding-choose_proportions-import-success = 导入成功
onboarding-choose_proportions-import-failed = 导入失败
onboarding-choose_proportions-file_type = 身体比例文件
## Tracker manual proportions setup

View File

@@ -348,9 +348,20 @@ 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-leg_fk-reset_mounting_feet-description = 開啟腳部配戴重置,進行配戴重置時需要踮起腳尖。
settings-general-fk_settings-leg_fk-reset_mounting_feet = 腳部配戴重置
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-reset_mode-description = 更改配戴重置時,手臂需要做出的姿勢。
settings-general-fk_settings-arm_fk-back = 收肘姿勢
settings-general-fk_settings-arm_fk-back-description = 預設模式,重置時手肘朝後,前臂向前。
settings-general-fk_settings-arm_fk-tpose_up = T 型姿勢(抬起)
settings-general-fk_settings-arm_fk-tpose_up-description = 完整重置時手臂向下,呈立正姿勢;配戴重置時手臂向兩側伸展,與身體呈 90 度。
settings-general-fk_settings-arm_fk-tpose_down = T 型姿勢(放下)
settings-general-fk_settings-arm_fk-tpose_down-description = 完整重置時手臂向兩側伸展,與身體呈 90 度;配戴重置時手臂向下,呈立正姿勢。
settings-general-fk_settings-arm_fk-forward = 向前伸展
settings-general-fk_settings-arm_fk-forward-description = 重置時手臂向前伸展,與身體呈 90 度,可用於坐姿進行虛擬直播。
settings-general-fk_settings-skeleton_settings-toggles = 骨架設定
settings-general-fk_settings-skeleton_settings-description = 開啟或關閉骨架設定。建議保持這些設定開啟。
settings-general-fk_settings-skeleton_settings-extended_spine_model = 延伸脊椎模型
@@ -358,12 +369,13 @@ settings-general-fk_settings-skeleton_settings-extended_pelvis_model = 延伸骨
settings-general-fk_settings-skeleton_settings-extended_knees_model = 延伸膝蓋模型
settings-general-fk_settings-skeleton_settings-ratios = 骨架比例
settings-general-fk_settings-skeleton_settings-ratios-description = 修改骨架設定的參數,您可能需要在修改後調整軀幹比例。
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_hip = 從胸部與臀部推算腰部
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_legs = 從胸部與腿部推算腰部
settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = 從胸部與腿部推算臀部
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = 從腰部與腿部推算臀部
settings-general-fk_settings-skeleton_settings-interp_hip_legs = 臀部的偏航軸與翻滾軸與腿部計算平均
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = 膝部的偏航軸與翻滾軸與腳踝計算平均
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_hip = 推算腰部定位時,胸部與臀部定位使用的比例
settings-general-fk_settings-skeleton_settings-impute_waist_from_chest_legs = 推算腰部定位時,胸部與腿部定位使用的比例
settings-general-fk_settings-skeleton_settings-impute_hip_from_chest_legs = 推算臀部定位時,胸部與腿部定位使用的比例
settings-general-fk_settings-skeleton_settings-impute_hip_from_waist_legs = 推算臀部定位時, 腰部與腿部定位使用的比例
settings-general-fk_settings-skeleton_settings-interp_hip_legs = 臀部的偏航軸與翻滾軸,混合腿部定位的比例
settings-general-fk_settings-skeleton_settings-interp_knee_tracker_ankle = 膝部的偏航軸與翻滾軸,混合腳踝定位的比例
settings-general-fk_settings-skeleton_settings-interp_knee_ankle = 將膝部的偏航軸與翻滾軸與腳踝計算平均
settings-general-fk_settings-self_localization-title = 動作捕捉模式
settings-general-fk_settings-self_localization-description = 動作捕捉模式允許在沒有頭戴顯示器或其他追蹤器時,粗略的追蹤身體骨架的定位。請注意,本功能需要腳部與頭部的追蹤器,並且本功能仍在實驗階段。
settings-general-fk_settings-vive_emulation-title = Vive 模擬
@@ -797,6 +809,9 @@ onboarding-choose_proportions-manual_proportions = 手動軀幹比例校正
onboarding-choose_proportions-manual_proportions-subtitle = 適合進行微調
onboarding-choose_proportions-manual_proportions-description = 本選項可以讓你直接修改軀幹比例的設定值
onboarding-choose_proportions-export = 匯出軀幹比例
onboarding-choose_proportions-import = 匯入軀幹比例
onboarding-choose_proportions-import-success = 匯入成功
onboarding-choose_proportions-import-failed = 匯入失敗
onboarding-choose_proportions-file_type = 軀幹比例描述檔
## Tracker manual proportions setup
@@ -855,7 +870,7 @@ 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 = 錄製結果

5
gui/public/logo.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-miterlimit="10" version="1.1" viewBox="0 0 380 380" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<style>svg { background-color: #663499; }</style>
<rect id="bg" width="100%" height="100%" fill="#663499"/><g id="logo" fill="none" stroke="#fff"><path id="left" d="m72.867 191.74 37-39 39 36" stroke-width="13.62px"/><path id="right" d="m208.87 187.74 38-35 36 38" stroke-width="13.62px"/><path id="outer" d="m56.867 253.74s130.61-31.182 248 5c13.45 4.146 20.244 2.975 20-8s1.909-126.06-46-131" stroke-linecap="square" stroke-width="17px"/></g>
</svg>

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,7 +1,16 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"name": "SlimeVR GUI",
"short_name": "SlimeVR GUI",
"description": "A web interface for controlling the SlimeVR Server software",
"display": "standalone",
"theme_color": "#663499",
"background_color": "#663499",
"icons": [
{
"src": "logo.svg",
"type": "image/svg+xml",
"sizes": "any 512x512 192x192"
},
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
@@ -17,9 +26,5 @@
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
]
}

View File

@@ -30,11 +30,11 @@ serde_json = "1"
serde = { version = "1", features = ["derive"] }
tauri = { version = "2.0.0-alpha.10", features = ["devtools"] }
tauri-runtime = "0.13.0-alpha.6"
tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-os = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-shell = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-window = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2", features = [
tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "4ab90f048eab2918344f97dc8e04413a404e392d" }
tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "4ab90f048eab2918344f97dc8e04413a404e392d" }
tauri-plugin-os = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "4ab90f048eab2918344f97dc8e04413a404e392d" }
tauri-plugin-shell = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "4ab90f048eab2918344f97dc8e04413a404e392d" }
tauri-plugin-window = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "4ab90f048eab2918344f97dc8e04413a404e392d", features = [
"devtools",
] }
flexi_logger = "0.25"

View File

@@ -35,7 +35,6 @@ import { SerialDetectionModal } from './components/SerialDetectionModal';
import { VRCOSCSettings } from './components/settings/pages/VRCOSCSettings';
import { TopBar } from './components/TopBar';
import { TrackerSettingsPage } from './components/tracker/TrackerSettings';
import { useConfig } from './hooks/config';
import { OSCRouterSettings } from './components/settings/pages/OSCRouterSettings';
import { useLocalization } from '@fluent/react';
import * as os from '@tauri-apps/plugin-os';
@@ -52,6 +51,7 @@ import { useBreakpoint } from './hooks/breakpoint';
import { VRModePage } from './components/vr-mode/VRModePage';
import { InterfaceSettings } from './components/settings/pages/InterfaceSettings';
import { error, log } from './utils/logging';
import { AppLayout } from './AppLayout';
export const GH_REPO = 'SlimeVR/SlimeVR-Server';
export const VersionContext = createContext('');
@@ -59,92 +59,94 @@ export const DOCS_SITE = 'https://docs.slimevr.dev';
export const SLIMEVR_DISCORD = 'https://discord.gg/slimevr';
function Layout() {
const { loading } = useConfig();
if (loading) return <></>;
const { isMobile } = useBreakpoint('mobile');
return (
<>
<SerialDetectionModal></SerialDetectionModal>
<VersionUpdateModal></VersionUpdateModal>
<Routes>
<Route
path="/"
element={
<MainLayoutRoute isMobile={isMobile}>
<Home />
</MainLayoutRoute>
}
/>
<Route
path="/vr-mode"
element={
<MainLayoutRoute isMobile={isMobile}>
<VRModePage />
</MainLayoutRoute>
}
/>
<Route
path="/tracker/:trackernum/:deviceid"
element={
<MainLayoutRoute background={false} isMobile={isMobile}>
<TrackerSettingsPage />
</MainLayoutRoute>
}
/>
<Route
path="/settings"
element={
<SettingsLayoutRoute>
<Outlet></Outlet>
</SettingsLayoutRoute>
}
>
<Route path="trackers" element={<GeneralSettings />} />
<Route path="serial" element={<Serial />} />
<Route path="osc/router" element={<OSCRouterSettings />} />
<Route path="osc/vrchat" element={<VRCOSCSettings />} />
<Route path="osc/vmc" element={<VMCSettings />} />
<Route path="interface" element={<InterfaceSettings />} />
<Route element={<AppLayout />}>
<Route
path="/"
element={
<MainLayoutRoute isMobile={isMobile}>
<Home />
</MainLayoutRoute>
}
/>
<Route
path="/vr-mode"
element={
<MainLayoutRoute isMobile={isMobile}>
<VRModePage />
</MainLayoutRoute>
}
/>
<Route
path="/tracker/:trackernum/:deviceid"
element={
<MainLayoutRoute background={false} isMobile={isMobile}>
<TrackerSettingsPage />
</MainLayoutRoute>
}
/>
<Route
path="/settings"
element={
<SettingsLayoutRoute>
<Outlet />
</SettingsLayoutRoute>
}
>
<Route path="trackers" element={<GeneralSettings />} />
<Route path="serial" element={<Serial />} />
<Route path="osc/router" element={<OSCRouterSettings />} />
<Route path="osc/vrchat" element={<VRCOSCSettings />} />
<Route path="osc/vmc" element={<VMCSettings />} />
<Route path="interface" element={<InterfaceSettings />} />
</Route>
<Route
path="/onboarding"
element={
<OnboardingLayout>
<Outlet />
</OnboardingLayout>
}
>
<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>
<Route path="mounting/auto" element={<AutomaticMountingPage />} />
<Route path="mounting/manual" element={<ManualMountingPage />} />
<Route path="reset-tutorial" element={<ResetTutorialPage />} />
<Route
path="body-proportions/choose"
element={<ProportionsChoose />}
/>
<Route
path="body-proportions/auto"
element={<AutomaticProportionsPage />}
/>
<Route
path="body-proportions/manual"
element={<ManualProportionsPage />}
/>
<Route path="done" element={<DonePage />} />
</Route>
<Route path="*" element={<TopBar></TopBar>}></Route>
</Route>
<Route
path="/onboarding"
element={
<OnboardingLayout>
<Outlet></Outlet>
</OnboardingLayout>
}
>
<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>
<Route path="mounting/auto" element={<AutomaticMountingPage />} />
<Route path="mounting/manual" element={<ManualMountingPage />} />
<Route path="reset-tutorial" element={<ResetTutorialPage />} />
<Route
path="body-proportions/choose"
element={<ProportionsChoose />}
/>
<Route
path="body-proportions/auto"
element={<AutomaticProportionsPage />}
/>
<Route
path="body-proportions/manual"
element={<ManualProportionsPage />}
/>
<Route path="done" element={<DonePage />} />
</Route>
<Route path="*" element={<TopBar></TopBar>}></Route>
</Routes>
</>
);

51
gui/src/AppLayout.tsx Normal file
View File

@@ -0,0 +1,51 @@
import { useLayoutEffect } from 'react';
import { useConfig } from './hooks/config';
import { Outlet, useNavigate } from 'react-router-dom';
export function AppLayout() {
const { loading, config } = useConfig();
const navigate = useNavigate();
useLayoutEffect(() => {
if (loading || !config) return;
if (config.theme !== undefined) {
document.documentElement.dataset.theme = config.theme;
}
if (config.fonts !== undefined) {
document.documentElement.style.setProperty(
'--font-name',
config.fonts.map((x) => `"${x}"`).join(',')
);
}
if (config.textSize !== undefined) {
document.documentElement.style.setProperty(
'--font-size',
`${config.textSize}rem`
);
}
}, [config, loading]);
useLayoutEffect(() => {
if (config && !config.doneOnboarding) {
navigate('/onboarding/home');
}
}, [config?.doneOnboarding]);
// const location = useLocation();
// const navigationType = useNavigationType();
// useEffect(() => {
// if (import.meta.env.PROD) return;
// console.log('The current URL is', { ...location });
// console.log('The last navigation action was', navigationType);
// }, [location, navigationType]);
if (loading) return <></>;
return (
<>
<Outlet />
</>
);
}

View File

@@ -5,7 +5,7 @@ import {
RecordBVHStatusT,
RpcMessage,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { RecordIcon } from './commons/icon/RecordIcon';

View File

@@ -1,6 +1,6 @@
import { useLocalization } from '@fluent/react';
import { ClearDriftCompensationRequestT, RpcMessage } from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { TrashIcon } from './commons/icon/TrashIcon';

View File

@@ -1,11 +1,11 @@
import { useLocalization } from '@fluent/react';
import { ClearMountingResetRequestT, RpcMessage } from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { TrashIcon } from './commons/icon/TrashIcon';
import { useTrackers } from '../hooks/tracker';
import { useTrackers } from '@/hooks/tracker';
import { Quaternion } from 'three';
import { QuaternionFromQuatT, similarQuaternions } from '../maths/quaternion';
import { QuaternionFromQuatT, similarQuaternions } from '@/maths/quaternion';
import { useMemo } from 'react';
const _q = new Quaternion();

View File

@@ -6,10 +6,10 @@ import {
RpcMessage,
SettingsRequestT,
} from 'solarxr-protocol';
import { useElemSize, useLayout } from '../hooks/layout';
import { useElemSize, useLayout } from '@/hooks/layout';
import { Navbar } from './Navbar';
import { TopBar } from './TopBar';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { WidgetsComponent } from './WidgetsComponent';
export function MainLayoutRoute({

View File

@@ -8,7 +8,7 @@ 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';
import { useBreakpoint } from '@/hooks/breakpoint';
export function NavButton({
to,

View File

@@ -6,9 +6,9 @@ import {
RpcMessage,
SerialDeviceT,
} from 'solarxr-protocol';
import { useConfig } from '../hooks/config';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWifiForm, WifiFormData } from '../hooks/wifi-form';
import { useConfig } from '@/hooks/config';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { useWifiForm, WifiFormData } from '@/hooks/wifi-form';
import { BaseModal } from './commons/BaseModal';
import { Button } from './commons/Button';
import { BulbIcon } from './commons/icon/BulbIcon';

View File

@@ -6,7 +6,7 @@ import {
ServerInfosRequestT,
ServerInfosResponseT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { CloseIcon } from './commons/icon/CloseIcon';
import { MaximiseIcon } from './commons/icon/MaximiseIcon';
import { MinimiseIcon } from './commons/icon/MinimiseIcon';
@@ -15,10 +15,10 @@ import { ProgressBar } from './commons/ProgressBar';
import { Typography } from './commons/Typography';
import { DownloadIcon } from './commons/icon/DownloadIcon';
import { open } from '@tauri-apps/plugin-shell';
import { GH_REPO, VersionContext, DOCS_SITE } from '../App';
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 { useBreakpoint, useIsTauri } from '@/hooks/breakpoint';
import { GearIcon } from './commons/icon/GearIcon';
import { invoke } from '@tauri-apps/api';

View File

@@ -1,7 +1,7 @@
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { SetPauseTrackingRequestT, RpcMessage } from 'solarxr-protocol';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { BigButton } from './commons/BigButton';
import { PlayIcon } from './commons/icon/PlayIcon';
import { PauseIcon } from './commons/icon/PauseIcon';

View File

@@ -5,8 +5,8 @@ import { Button } from './commons/Button';
import { Typography } from './commons/Typography';
import { open } from '@tauri-apps/plugin-shell';
import semver from 'semver';
import { GH_REPO, VersionContext } from '../App';
import { error } from '../utils/logging';
import { GH_REPO, VersionContext } from '@/App';
import { error } from '@/utils/logging';
export function VersionUpdateModal() {
const { l10n } = useLocalization();

View File

@@ -6,7 +6,7 @@ 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 { useConfig } from '@/hooks/config';
import {
ResetType,
RpcMessage,
@@ -15,9 +15,9 @@ import {
StatusData,
} from 'solarxr-protocol';
import { useEffect, useMemo, useState } from 'react';
import { parseStatusToLocale, useStatusContext } from '../hooks/status-system';
import { useWebsocketAPI } from '../hooks/websocket-api';
import { useAppContext } from '../hooks/app';
import { parseStatusToLocale, useStatusContext } from '@/hooks/status-system';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { useAppContext } from '@/hooks/app';
import { ClearMountingButton } from './ClearMountingButton';
export function WidgetsComponent() {

View File

@@ -8,8 +8,8 @@ import {
useState,
} from 'react';
import { BodyPart, TrackerDataT } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../hooks/app';
import { useTracker } from '../../hooks/tracker';
import { FlatDeviceTracker } from '@/hooks/app';
import { useTracker } from '@/hooks/tracker';
import { PersonFrontIcon } from './PersonFrontIcon';
interface SlotDot {

View File

@@ -2,7 +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';
import { useBreakpoint } from '@/hooks/breakpoint';
export function BodyInteractions({
leftControls,

View File

@@ -1,5 +1,5 @@
import { BodyPart } from 'solarxr-protocol';
import { useLocaleConfig } from '../../i18n/config';
import { useLocaleConfig } from '@/i18n/config';
import { AnkleIcon } from './icon/AnkleIcon';
import { ChestIcon } from './icon/ChestIcon';
import { ControllerIcon } from './icon/ControllerIcon';

View File

@@ -6,7 +6,7 @@ import {
UseFormGetValues,
useWatch,
} from 'react-hook-form';
import { a11yClick } from '../../utils/a11y';
import { a11yClick } from '@/utils/a11y';
export interface DropdownItem {
label: string;

View File

@@ -1,8 +1,8 @@
import { useLocalization } from '@fluent/react';
import { useEffect, useMemo, useContext } from 'react';
import { useForm } from 'react-hook-form';
import { useConfig } from '../../hooks/config';
import { langs, LangContext } from '../../i18n/config';
import { useConfig } from '@/hooks/config';
import { langs, LangContext } from '@/i18n/config';
import { Dropdown, DropdownDirection } from './Dropdown';
export function LangSelector({

View File

@@ -1,19 +1,19 @@
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 { useConfig } from '@/hooks/config';
import { useTrackers } from '@/hooks/tracker';
import { Typography } from '@/components/commons/Typography';
import { TrackerCard } from '@/components/tracker/TrackerCard';
import { TrackersTable } from '@/components/tracker/TrackersTable';
import {
parseStatusToLocale,
trackerStatusRelated,
useStatusContext,
} from '../../hooks/status-system';
} from '@/hooks/status-system';
import { useMemo } from 'react';
import { WarningBox } from '../commons/TipBox';
import { HeadsetIcon } from '../commons/icon/HeadsetIcon';
import { WarningBox } from '@/components/commons/TipBox';
import { HeadsetIcon } from '@/components/commons/icon/HeadsetIcon';
import classNames from 'classnames';
const DONT_REPEAT_STATUSES = [StatusData.StatusTrackerReset];

View File

@@ -6,18 +6,18 @@ import {
RpcMessage,
StatusData,
} from 'solarxr-protocol';
import { useConfig } from '../../hooks/config';
import { useCountdown } from '../../hooks/countdown';
import { useWebsocketAPI } from '../../hooks/websocket-api';
import { playSoundOnResetStarted } from '../../sounds/sounds';
import { BigButton } from '../commons/BigButton';
import { Button } from '../commons/Button';
import { useConfig } from '@/hooks/config';
import { useCountdown } from '@/hooks/countdown';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { playSoundOnResetStarted } from '@/sounds/sounds';
import { BigButton } from '@/components/commons/BigButton';
import { Button } from '@/components/commons/Button';
import {
MountingResetIcon,
YawResetIcon,
FullResetIcon,
} from '../commons/icon/ResetIcon';
import { useStatusContext } from '../../hooks/status-system';
} from '@/components/commons/icon/ResetIcon';
import { useStatusContext } from '@/hooks/status-system';
export function ResetButton({
type,

View File

@@ -1,9 +1,9 @@
import { useMemo } from 'react';
import { BodyPart } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../hooks/app';
import { useTrackers } from '../../hooks/tracker';
import { BodyInteractions } from '../commons/BodyInteractions';
import { TrackerPartCard } from '../tracker/TrackerPartCard';
import { FlatDeviceTracker } from '@/hooks/app';
import { useTrackers } from '@/hooks/tracker';
import { BodyInteractions } from '@/components/commons/BodyInteractions';
import { TrackerPartCard } from '@/components/tracker/TrackerPartCard';
import { BodyPartError } from './pages/trackers-assign/TrackerAssignment';
export const SPINE_PARTS = [

View File

@@ -1,7 +1,7 @@
import { Button } from '../commons/Button';
import { WarningBox } from '../commons/TipBox';
import { Button } from '@/components/commons/Button';
import { WarningBox } from '@/components/commons/TipBox';
import { Localized, useLocalization } from '@fluent/react';
import { BaseModal } from '../commons/BaseModal';
import { BaseModal } from '@/components/commons/BaseModal';
import ReactModal from 'react-modal';
export function NeckWarningModal({

View File

@@ -1,8 +1,5 @@
import { ReactNode } from 'react';
import {
OnboardingContextC,
useProvideOnboarding,
} from '../../hooks/onboarding';
import { OnboardingContextC, useProvideOnboarding } from '@/hooks/onboarding';
export function OnboardingContextProvider({
children,

View File

@@ -1,9 +1,9 @@
import { ReactNode, useState } from 'react';
import { useLayout } from '../../hooks/layout';
import { useOnboarding } from '../../hooks/onboarding';
import { MainLayoutRoute } from '../MainLayout';
import { TopBar } from '../TopBar';
import { useBreakpoint } from '../../hooks/breakpoint';
import { useLayout } from '@/hooks/layout';
import { useOnboarding } from '@/hooks/onboarding';
import { MainLayoutRoute } from '@/components/MainLayout';
import { TopBar } from '@/components/TopBar';
import { useBreakpoint } from '@/hooks/breakpoint';
import { SkipSetupButton } from './SkipSetupButton';
import { SkipSetupWarningModal } from './SkipSetupWarningModal';

View File

@@ -1,6 +1,6 @@
import classNames from 'classnames';
import { useEffect } from 'react';
import { EscapeIcon } from '../commons/icon/EscapeIcon';
import { EscapeIcon } from '@/components/commons/icon/EscapeIcon';
export function SkipSetupButton({
modalVisible,

View File

@@ -1,7 +1,7 @@
import { Button } from '../commons/Button';
import { WarningBox } from '../commons/TipBox';
import { Button } from '@/components/commons/Button';
import { WarningBox } from '@/components/commons/TipBox';
import { Localized, useLocalization } from '@fluent/react';
import { BaseModal } from '../commons/BaseModal';
import { BaseModal } from '@/components/commons/BaseModal';
import ReactModal from 'react-modal';
import { useNavigate } from 'react-router-dom';

View File

@@ -7,9 +7,9 @@ import {
useRef,
useState,
} from 'react';
import { useElemSize } from '../../hooks/layout';
import { CheckIcon } from '../commons/icon/CheckIcon';
import { Typography } from '../commons/Typography';
import { useElemSize } from '@/hooks/layout';
import { CheckIcon } from '@/components/commons/icon/CheckIcon';
import { Typography } from '@/components/commons/Typography';
type StepComponentType = FC<{
nextStep: () => void;

View File

@@ -1,13 +1,13 @@
import { Localized, useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { Typography } from '../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useMemo, useState } from 'react';
import { ProgressBar } from '../../commons/ProgressBar';
import { LoaderIcon, SlimeState } from '../../commons/icon/LoaderIcon';
import { useCountdown } from '../../../hooks/countdown';
import { ProgressBar } from '@/components/commons/ProgressBar';
import { LoaderIcon, SlimeState } from '@/components/commons/icon/LoaderIcon';
import { useCountdown } from '@/hooks/countdown';
import classNames from 'classnames';
import { TaybolIcon } from '../../commons/icon/TaybolIcon';
import { TaybolIcon } from '@/components/commons/icon/TaybolIcon';
export enum CalibrationStatus {
SUCCESS,

View File

@@ -9,19 +9,19 @@ import {
WifiProvisioningStatus,
WifiProvisioningStatusResponseT,
} from 'solarxr-protocol';
import { useLayout } from '../../../hooks/layout';
import { useOnboarding } from '../../../hooks/onboarding';
import { useTrackers } from '../../../hooks/tracker';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { ArrowLink } from '../../commons/ArrowLink';
import { Button } from '../../commons/Button';
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 { useBnoExists } from '../../../hooks/imu-logic';
import { useBreakpoint } from '../../../hooks/breakpoint';
import { useLayout } from '@/hooks/layout';
import { useOnboarding } from '@/hooks/onboarding';
import { useTrackers } from '@/hooks/tracker';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { ArrowLink } from '@/components/commons/ArrowLink';
import { Button } from '@/components/commons/Button';
import { LoaderIcon, SlimeState } from '@/components/commons/icon/LoaderIcon';
import { ProgressBar } from '@/components/commons/ProgressBar';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { TrackerCard } from '@/components/tracker/TrackerCard';
import { useBnoExists } from '@/hooks/imu-logic';
import { useBreakpoint } from '@/hooks/breakpoint';
const BOTTOM_HEIGHT = 80;

View File

@@ -1,8 +1,8 @@
import { useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { SlimeVRIcon } from '../../commons/icon/SimevrIcon';
import { Typography } from '../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { Button } from '@/components/commons/Button';
import { SlimeVRIcon } from '@/components/commons/icon/SimevrIcon';
import { Typography } from '@/components/commons/Typography';
export function DonePage() {
const { l10n } = useLocalization();

View File

@@ -1,8 +1,8 @@
import { useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../hooks/onboarding';
import { ArrowLink } from '../../commons/ArrowLink';
import { Button } from '../../commons/Button';
import { Typography } from '../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { ArrowLink } from '@/components/commons/ArrowLink';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
export function EnterVRPage() {
const { l10n } = useLocalization();

View File

@@ -1,9 +1,9 @@
import { useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { SlimeVRIcon } from '../../commons/icon/SimevrIcon';
import { LangSelector } from '../../commons/LangSelector';
import { Typography } from '../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { Button } from '@/components/commons/Button';
import { SlimeVRIcon } from '@/components/commons/icon/SimevrIcon';
import { LangSelector } from '@/components/commons/LangSelector';
import { Typography } from '@/components/commons/Typography';
export function HomePage() {
const { l10n } = useLocalization();

View File

@@ -1,7 +1,7 @@
import { useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../hooks/onboarding';
import { Button } from '../../commons/Button';
import { Typography } from '../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useState, useMemo, useEffect } from 'react';
import {
BodyPart,
@@ -12,12 +12,12 @@ import {
SettingsRequestT,
SettingsResponseT,
} from 'solarxr-protocol';
import { useTrackers } from '../../../hooks/tracker';
import { BodyDisplay } from '../../commons/BodyDisplay';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { useTrackers } from '@/hooks/tracker';
import { BodyDisplay } from '@/components/commons/BodyDisplay';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import classNames from 'classnames';
import { useBreakpoint } from '../../../hooks/breakpoint';
import { log } from '../../../utils/logging';
import { useBreakpoint } from '@/hooks/breakpoint';
import { log } from '@/utils/logging';
export function ResetTutorialPage() {
const { isMobile } = useBreakpoint('mobile');

View File

@@ -1,12 +1,12 @@
import { Localized, useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../hooks/onboarding';
import { useWifiForm } from '../../../hooks/wifi-form';
import { Button } from '../../commons/Button';
import { Input } from '../../commons/Input';
import { Typography } from '../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { useWifiForm } from '@/hooks/wifi-form';
import { Button } from '@/components/commons/Button';
import { Input } from '@/components/commons/Input';
import { Typography } from '@/components/commons/Typography';
import classNames from 'classnames';
import { useTrackers } from '../../../hooks/tracker';
import { useBnoExists } from '../../../hooks/imu-logic';
import { useTrackers } from '@/hooks/tracker';
import { useBnoExists } from '@/hooks/imu-logic';
export function WifiCredsPage() {
const { l10n } = useLocalization();

View File

@@ -1,9 +1,9 @@
import { useLocalization } from '@fluent/react';
import { useOnboarding } from '../../../../hooks/onboarding';
import { Button } from '../../../commons/Button';
import { Typography } from '../../../commons/Typography';
import { useTrackers } from '../../../../hooks/tracker';
import { useBnoExists } from '../../../../hooks/imu-logic';
import { useOnboarding } from '@/hooks/onboarding';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useTrackers } from '@/hooks/tracker';
import { useBnoExists } from '@/hooks/imu-logic';
import { StickerSlime } from './StickerSlime';
import { TrackerArrow } from './TrackerArrow';
import { ExtensionArrow } from './ExtensionArrow';

View File

@@ -1,21 +1,18 @@
import { useLocalization } from '@fluent/react';
import { RpcMessage, SkeletonResetAllRequestT } from 'solarxr-protocol';
import {
AutoboneContextC,
useProvideAutobone,
} from '../../../../hooks/autobone';
import { useOnboarding } from '../../../../hooks/onboarding';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import { Button } from '../../../commons/Button';
import { Typography } from '../../../commons/Typography';
import { StepperSlider } from '../../StepperSlider';
import { AutoboneContextC, useProvideAutobone } from '@/hooks/autobone';
import { useOnboarding } from '@/hooks/onboarding';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { StepperSlider } from '@/components/onboarding/StepperSlider';
import { DoneStep } from './autobone-steps/Done';
import { RequirementsStep } from './autobone-steps/Requirements';
import { PutTrackersOnStep } from './autobone-steps/PutTrackersOn';
import { Recording } from './autobone-steps/Recording';
import { StartRecording } from './autobone-steps/StartRecording';
import { VerifyResultsStep } from './autobone-steps/VerifyResults';
import { useCountdown } from '../../../../hooks/countdown';
import { useCountdown } from '@/hooks/countdown';
import { CheckHeight } from './autobone-steps/СheckHeight';
export function AutomaticProportionsPage() {

View File

@@ -12,12 +12,15 @@ import {
LabelType,
ProportionChangeType,
useManualProportions,
} from '../../../../hooks/manual-proportions';
import { useLocaleConfig } from '../../../../i18n/config';
import { Typography } from '../../../commons/Typography';
import { ArrowDownIcon, ArrowUpIcon } from '../../../commons/icon/ArrowIcons';
import { useBreakpoint } from '../../../../hooks/breakpoint';
import { debounce } from '../../../../hooks/timeout';
} from '@/hooks/manual-proportions';
import { useLocaleConfig } from '@/i18n/config';
import { Typography } from '@/components/commons/Typography';
import {
ArrowDownIcon,
ArrowUpIcon,
} from '@/components/commons/icon/ArrowIcons';
import { useBreakpoint } from '@/hooks/breakpoint';
import { debounce } from '@/hooks/timeout';
function IncrementButton({
children,

View File

@@ -1,15 +1,15 @@
import { useForm } from 'react-hook-form';
import { RpcMessage, SkeletonResetAllRequestT } from 'solarxr-protocol';
import { useOnboarding } from '../../../../hooks/onboarding';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import { Button } from '../../../commons/Button';
import { CheckBox } from '../../../commons/Checkbox';
import { PersonFrontIcon } from '../../../commons/PersonFrontIcon';
import { Typography } from '../../../commons/Typography';
import { useOnboarding } from '@/hooks/onboarding';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { Button } from '@/components/commons/Button';
import { CheckBox } from '@/components/commons/Checkbox';
import { PersonFrontIcon } from '@/components/commons/PersonFrontIcon';
import { Typography } from '@/components/commons/Typography';
import { BodyProportions } from './BodyProportions';
import { useLocalization } from '@fluent/react';
import { useEffect, useMemo } from 'react';
import { useBreakpoint } from '../../../../hooks/breakpoint';
import { useBreakpoint } from '@/hooks/breakpoint';
export function ButtonsControl() {
const { l10n } = useLocalization();

View File

@@ -1,25 +1,34 @@
import { useOnboarding } from '../../../../hooks/onboarding';
import { useOnboarding } from '@/hooks/onboarding';
import { Localized, useLocalization } from '@fluent/react';
import { useMemo, useState } from 'react';
import classNames from 'classnames';
import { Typography } from '../../../commons/Typography';
import { Button } from '../../../commons/Button';
import { Typography } from '@/components/commons/Typography';
import { Button } from '@/components/commons/Button';
import {
SkeletonConfigResponseT,
RpcMessage,
SkeletonConfigRequestT,
SkeletonBone,
ChangeSkeletonConfigRequestT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import saveAs from 'file-saver';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { save } from '@tauri-apps/plugin-dialog';
import { writeTextFile } from '@tauri-apps/plugin-fs';
import { useIsTauri } from '../../../../hooks/breakpoint';
import { useAppContext } from '../../../../hooks/app';
import { error } from '../../../../utils/logging';
import { useIsTauri } from '@/hooks/breakpoint';
import { useAppContext } from '@/hooks/app';
import { error } from '@/utils/logging';
import { fileOpen, fileSave } from 'browser-fs-access';
import { useDebouncedEffect } from '@/hooks/timeout';
export const MIN_HEIGHT = 0.4;
export const MAX_HEIGHT = 4;
export const DEFAULT_HEIGHT = 1.5;
export const CURRENT_EXPORT_VERSION = 1;
enum ImportStatus {
FAILED,
SUCCESS,
OK,
}
export function ProportionsChoose() {
const isTauri = useIsTauri();
@@ -27,8 +36,15 @@ export function ProportionsChoose() {
const { applyProgress, state } = useOnboarding();
const { useRPCPacket, sendRPCPacket } = useWebsocketAPI();
const [animated, setAnimated] = useState(false);
const [importState, setImportState] = useState(ImportStatus.OK);
const { computedTrackers } = useAppContext();
useDebouncedEffect(
() => setImportState(ImportStatus.OK),
[importState],
2000
);
const hmdTracker = useMemo(
() =>
computedTrackers.find(
@@ -48,9 +64,27 @@ export function ProportionsChoose() {
[hmdTracker?.tracker.position?.y]
);
const importStatusKey = useMemo(() => {
switch (importState) {
case ImportStatus.FAILED:
return 'onboarding-choose_proportions-import-failed';
case ImportStatus.SUCCESS:
return 'onboarding-choose_proportions-import-success';
case ImportStatus.OK:
return 'onboarding-choose_proportions-import';
}
}, [importState]);
useRPCPacket(
RpcMessage.SkeletonConfigResponse,
(data: SkeletonConfigResponseT) => {
(data: SkeletonConfigExport) => {
// Convert the skeleton part enums into a string
data.skeletonParts.forEach((x) => {
if (typeof x.bone === 'number')
x.bone = SkeletonBone[x.bone] as SkeletonBoneKey;
});
data.version = CURRENT_EXPORT_VERSION;
const blob = new Blob([JSON.stringify(data)], {
type: 'application/json',
});
@@ -71,13 +105,52 @@ export function ProportionsChoose() {
error(err);
});
} else {
saveAs(blob, 'body-proportions.json');
fileSave(blob, {
fileName: 'body-proportions.json',
extensions: ['.json'],
});
}
}
);
applyProgress(0.85);
const onImport = async () => {
const file = await fileOpen({
mimeTypes: ['application/json'],
});
const text = await file.text();
const config = JSON.parse(text) as SkeletonConfigExport;
if (
!config?.skeletonParts?.length ||
!Array.isArray(config.skeletonParts)
) {
error(
'failed to import body proportions because skeletonParts is not an array/empty'
);
return setImportState(ImportStatus.FAILED);
}
for (const bone of [...config.skeletonParts]) {
if (
(typeof bone.bone === 'string' && !(bone.bone in SkeletonBone)) ||
(typeof bone.bone === 'number' &&
typeof SkeletonBone[bone.bone] !== 'string')
) {
error(
`failed to import body proportions because ${bone.bone} is not a valid bone`
);
return setImportState(ImportStatus.FAILED);
}
}
parseConfigImport(config).forEach((req) =>
sendRPCPacket(RpcMessage.ChangeSkeletonConfigRequest, req)
);
setImportState(ImportStatus.SUCCESS);
};
return (
<>
<div className="flex flex-col gap-5 h-full items-center w-full xs:justify-center mobile:overflow-y-auto relative px-4 pb-4">
@@ -196,7 +269,7 @@ export function ProportionsChoose() {
</div>
</div>
</div>
<div className="flex flex-row">
<div className="flex flex-row gap-3">
{!state.alonePage && (
<Button variant="secondary" to="/onboarding/reset-tutorial">
{l10n.getString('onboarding-previous_step')}
@@ -214,9 +287,46 @@ export function ProportionsChoose() {
>
{l10n.getString('onboarding-choose_proportions-export')}
</Button>
<Button
variant={!state.alonePage ? 'secondary' : 'tertiary'}
className={classNames(
'transition-colors',
importState === ImportStatus.FAILED && 'bg-status-critical',
importState === ImportStatus.SUCCESS && 'bg-status-success'
)}
onClick={onImport}
>
{l10n.getString(importStatusKey)}
</Button>
</div>
</div>
</div>
</>
);
}
function parseConfigImport(
config: SkeletonConfigExport
): ChangeSkeletonConfigRequestT[] {
if (!config.version) config.version = 1;
if (config.version < 1) {
// Add config migration stuff here, this one is just an example.
}
return config.skeletonParts.map((part) => {
const bone =
typeof part.bone === 'string' ? SkeletonBone[part.bone] : part.bone;
return new ChangeSkeletonConfigRequestT(bone, part.value);
});
}
type SkeletonBoneKey = keyof typeof SkeletonBone;
interface SkeletonConfigExport {
version?: number;
skeletonParts: {
bone: SkeletonBoneKey | SkeletonBone;
value: number;
}[];
}

View File

@@ -1,10 +1,10 @@
import { Localized, useLocalization } from '@fluent/react';
import ReactModal from 'react-modal';
import { BaseModal } from '../../../../commons/BaseModal';
import { WarningBox } from '../../../../commons/TipBox';
import { Button } from '../../../../commons/Button';
import { A } from '../../../../commons/A';
import { DOCS_SITE, SLIMEVR_DISCORD } from '../../../../../App';
import { BaseModal } from '@/components/commons/BaseModal';
import { WarningBox } from '@/components/commons/TipBox';
import { Button } from '@/components/commons/Button';
import { A } from '@/components/commons/A';
import { DOCS_SITE, SLIMEVR_DISCORD } from '@/App';
export function AutoboneErrorModal({
isOpen = true,

View File

@@ -1,6 +1,6 @@
import { Typography } from '../../../../commons/Typography';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
import { Button } from '../../../../commons/Button';
import { Button } from '@/components/commons/Button';
export function DoneStep({ variant }: { variant: 'onboarding' | 'alone' }) {
const { l10n } = useLocalization();

View File

@@ -1,9 +1,9 @@
import { useBreakpoint } from '../../../../../hooks/breakpoint';
import { useTrackers } from '../../../../../hooks/tracker';
import { BodyDisplay } from '../../../../commons/BodyDisplay';
import { Button } from '../../../../commons/Button';
import { TipBox } from '../../../../commons/TipBox';
import { Typography } from '../../../../commons/Typography';
import { useBreakpoint } from '@/hooks/breakpoint';
import { useTrackers } from '@/hooks/tracker';
import { BodyDisplay } from '@/components/commons/BodyDisplay';
import { Button } from '@/components/commons/Button';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function PutTrackersOnStep({

View File

@@ -1,8 +1,8 @@
import { ReactNode, useEffect, useState } from 'react';
import { ProcessStatus, useAutobone } from '../../../../../hooks/autobone';
import { ProgressBar } from '../../../../commons/ProgressBar';
import { TipBox } from '../../../../commons/TipBox';
import { Typography } from '../../../../commons/Typography';
import { ProcessStatus, useAutobone } from '@/hooks/autobone';
import { ProgressBar } from '@/components/commons/ProgressBar';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
import { P, match } from 'ts-pattern';
import { AutoboneErrorModal } from './AutoboneErrorModal';

View File

@@ -1,5 +1,5 @@
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function RequirementsStep({

View File

@@ -1,7 +1,7 @@
import { useAutobone } from '../../../../../hooks/autobone';
import { Button } from '../../../../commons/Button';
import { TipBox } from '../../../../commons/TipBox';
import { Typography } from '../../../../commons/Typography';
import { useAutobone } from '@/hooks/autobone';
import { Button } from '@/components/commons/Button';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function StartRecording({

View File

@@ -1,7 +1,7 @@
import classNames from 'classnames';
import { ProcessStatus, useAutobone } from '../../../../../hooks/autobone';
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { ProcessStatus, useAutobone } from '@/hooks/autobone';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function VerifyResultsStep({

View File

@@ -5,16 +5,19 @@ import {
HeightResponseT,
RpcMessage,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../../../hooks/websocket-api';
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { Localized, useLocalization } from '@fluent/react';
import { useForm } from 'react-hook-form';
import { useMemo, useState } from 'react';
import { NumberSelector } from '../../../../commons/NumberSelector';
import { DEFAULT_HEIGHT, MIN_HEIGHT } from '../ProportionsChoose';
import { useLocaleConfig } from '../../../../../i18n/config';
import { useCountdown } from '../../../../../hooks/countdown';
import { NumberSelector } from '@/components/commons/NumberSelector';
import {
DEFAULT_HEIGHT,
MIN_HEIGHT,
} from '@/components/onboarding/pages/body-proportions/ProportionsChoose';
import { useLocaleConfig } from '@/i18n/config';
import { useCountdown } from '@/hooks/countdown';
interface HeightForm {
height: number;

View File

@@ -1,6 +1,6 @@
import { useOnboarding } from '../../../../hooks/onboarding';
import { Typography } from '../../../commons/Typography';
import { Step, StepperSlider } from '../../StepperSlider';
import { useOnboarding } from '@/hooks/onboarding';
import { Typography } from '@/components/commons/Typography';
import { Step, StepperSlider } from '@/components/onboarding/StepperSlider';
import { DoneStep } from './mounting-steps/Done';
import { MountingResetStep } from './mounting-steps/MountingReset';
import { PreparationStep } from './mounting-steps/Preparation';

View File

@@ -1,17 +1,17 @@
import { useMemo, useState } from 'react';
import { AssignTrackerRequestT, BodyPart, RpcMessage } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../../../hooks/app';
import { useOnboarding } from '../../../../hooks/onboarding';
import { useTrackers } from '../../../../hooks/tracker';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import { MountingOrientationDegreesToQuatT } from '../../../../maths/quaternion';
import { Button } from '../../../commons/Button';
import { TipBox } from '../../../commons/TipBox';
import { Typography } from '../../../commons/Typography';
import { BodyAssignment } from '../../BodyAssignment';
import { FlatDeviceTracker } from '@/hooks/app';
import { useOnboarding } from '@/hooks/onboarding';
import { useTrackers } from '@/hooks/tracker';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { MountingOrientationDegreesToQuatT } from '@/maths/quaternion';
import { Button } from '@/components/commons/Button';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { BodyAssignment } from '@/components/onboarding/BodyAssignment';
import { MountingSelectionMenu } from './MountingSelectionMenu';
import { useLocalization } from '@fluent/react';
import { useBreakpoint } from '../../../../hooks/breakpoint';
import { useBreakpoint } from '@/hooks/breakpoint';
import { Quaternion } from 'three';
export function ManualMountingPage() {

View File

@@ -1,10 +1,10 @@
import { useOnboarding } from '../../../../hooks/onboarding';
import { useOnboarding } from '@/hooks/onboarding';
import { useLocalization } from '@fluent/react';
import { useState } from 'react';
import { SkipSetupWarningModal } from '../../SkipSetupWarningModal';
import { SkipSetupWarningModal } from '@/components/onboarding/SkipSetupWarningModal';
import classNames from 'classnames';
import { Typography } from '../../../commons/Typography';
import { Button } from '../../../commons/Button';
import { Typography } from '@/components/commons/Typography';
import { Button } from '@/components/commons/Button';
export function MountingChoose() {
const { l10n } = useLocalization();

View File

@@ -1,17 +1,17 @@
import classNames from 'classnames';
import { MouseEventHandler } from 'react';
import ReactModal from 'react-modal';
import { useElemSize, useLayout } from '../../../../hooks/layout';
import { Button } from '../../../commons/Button';
import { Typography } from '../../../commons/Typography';
import { useElemSize, useLayout } from '@/hooks/layout';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
import { FootIcon } from '../../../commons/icon/FootIcon';
import { rotationToQuatMap } from '../../../../maths/quaternion';
import { FootIcon } from '@/components/commons/icon/FootIcon';
import { rotationToQuatMap } from '@/maths/quaternion';
import { Quaternion } from 'three';
import { SlimeUpIcon } from '../../../commons/icon/SlimeUpIcon';
import { SlimeUpIcon } from '@/components/commons/icon/SlimeUpIcon';
import { BodyPart } from 'solarxr-protocol';
import { PawIcon } from '../../../commons/icon/PawIcon';
import { useLocaleConfig } from '../../../../i18n/config';
import { PawIcon } from '@/components/commons/icon/PawIcon';
import { useLocaleConfig } from '@/i18n/config';
// All body parts that are right or left, are by default left!
export const mapPart: Record<

View File

@@ -1,5 +1,5 @@
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function DoneStep({

View File

@@ -1,9 +1,9 @@
import { ResetType } from 'solarxr-protocol';
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { ResetButton } from '../../../../home/ResetButton';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { ResetButton } from '@/components/home/ResetButton';
import { useLocalization } from '@fluent/react';
import { useBreakpoint } from '../../../../../hooks/breakpoint';
import { useBreakpoint } from '@/hooks/breakpoint';
export function MountingResetStep({
nextStep,

View File

@@ -1,9 +1,9 @@
import { ResetType } from 'solarxr-protocol';
import { Button } from '../../../../commons/Button';
import { Typography } from '../../../../commons/Typography';
import { ResetButton } from '../../../../home/ResetButton';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import { ResetButton } from '@/components/home/ResetButton';
import { useLocalization } from '@fluent/react';
import { useBreakpoint } from '../../../../../hooks/breakpoint';
import { useBreakpoint } from '@/hooks/breakpoint';
export function PreparationStep({
nextStep,

View File

@@ -1,9 +1,9 @@
import { useBreakpoint } from '../../../../../hooks/breakpoint';
import { useTrackers } from '../../../../../hooks/tracker';
import { BodyDisplay } from '../../../../commons/BodyDisplay';
import { Button } from '../../../../commons/Button';
import { TipBox } from '../../../../commons/TipBox';
import { Typography } from '../../../../commons/Typography';
import { useBreakpoint } from '@/hooks/breakpoint';
import { useTrackers } from '@/hooks/tracker';
import { BodyDisplay } from '@/components/commons/BodyDisplay';
import { Button } from '@/components/commons/Button';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function PutTrackersOnStep({

View File

@@ -14,21 +14,24 @@ import {
ChangeSettingsRequestT,
TapDetectionSetupNotificationT,
} from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../../../hooks/app';
import { useChokerWarning } from '../../../../hooks/choker-warning';
import { useOnboarding } from '../../../../hooks/onboarding';
import { useTrackers } from '../../../../hooks/tracker';
import { useWebsocketAPI } from '../../../../hooks/websocket-api';
import { Button } from '../../../commons/Button';
import { CheckBox } from '../../../commons/Checkbox';
import { TipBox } from '../../../commons/TipBox';
import { Typography } from '../../../commons/Typography';
import { ASSIGNMENT_RULES, BodyAssignment } from '../../BodyAssignment';
import { NeckWarningModal } from '../../NeckWarningModal';
import { FlatDeviceTracker } from '@/hooks/app';
import { useChokerWarning } from '@/hooks/choker-warning';
import { useOnboarding } from '@/hooks/onboarding';
import { useTrackers } from '@/hooks/tracker';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { Button } from '@/components/commons/Button';
import { CheckBox } from '@/components/commons/Checkbox';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import {
ASSIGNMENT_RULES,
BodyAssignment,
} from '@/components/onboarding/BodyAssignment';
import { NeckWarningModal } from '@/components/onboarding/NeckWarningModal';
import { TrackerSelectionMenu } from './TrackerSelectionMenu';
import { useConfig } from '../../../../hooks/config';
import { playTapSetupSound } from '../../../../sounds/sounds';
import { useBreakpoint } from '../../../../hooks/breakpoint';
import { useConfig } from '@/hooks/config';
import { playTapSetupSound } from '@/sounds/sounds';
import { useBreakpoint } from '@/hooks/breakpoint';
export type BodyPartError = {
label: string | undefined;

View File

@@ -1,13 +1,13 @@
import classNames from 'classnames';
import ReactModal from 'react-modal';
import { BodyPart } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../../../hooks/app';
import { useElemSize, useLayout } from '../../../../hooks/layout';
import { useTrackers } from '../../../../hooks/tracker';
import { Button } from '../../../commons/Button';
import { TipBox } from '../../../commons/TipBox';
import { Typography } from '../../../commons/Typography';
import { TrackerCard } from '../../../tracker/TrackerCard';
import { FlatDeviceTracker } from '@/hooks/app';
import { useElemSize, useLayout } from '@/hooks/layout';
import { useTrackers } from '@/hooks/tracker';
import { Button } from '@/components/commons/Button';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import { TrackerCard } from '@/components/tracker/TrackerCard';
import { useLocalization } from '@fluent/react';
export function TrackerSelectionMenu({

View File

@@ -1,5 +1,5 @@
import { ReactNode } from 'react';
import { AppContextC, useProvideAppContext } from '../../hooks/app';
import { AppContextC, useProvideAppContext } from '@/hooks/app';
export function AppContextProvider({ children }: { children: ReactNode }) {
const context = useProvideAppContext();

View File

@@ -1,6 +1,6 @@
import { ReactNode, useEffect, useContext } from 'react';
import { ConfigContextC, useConfigProvider } from '../../hooks/config';
import { DEFAULT_LOCALE, LangContext } from '../../i18n/config';
import { ConfigContextC, useConfigProvider } from '@/hooks/config';
import { DEFAULT_LOCALE, LangContext } from '@/i18n/config';
export function ConfigContextProvider({ children }: { children: ReactNode }) {
const context = useConfigProvider();

View File

@@ -1,8 +1,5 @@
import { ReactNode } from 'react';
import {
StatusSystemC,
useProvideStatusContext,
} from '../../hooks/status-system';
import { StatusSystemC, useProvideStatusContext } from '@/hooks/status-system';
export function StatusProvider({ children }: { children: ReactNode }) {
const context = useProvideStatusContext();

View File

@@ -1,10 +1,10 @@
import { ReactNode, useEffect } from 'react';
import { useElemSize, useLayout } from '../../hooks/layout';
import { Navbar } from '../Navbar';
import { TopBar } from '../TopBar';
import { useElemSize, useLayout } from '@/hooks/layout';
import { Navbar } from '@/components/Navbar';
import { TopBar } from '@/components/TopBar';
import { SettingsSidebar } from './SettingsSidebar';
import { useBreakpoint } from '../../hooks/breakpoint';
import { Dropdown } from '../commons/Dropdown';
import { useBreakpoint } from '@/hooks/breakpoint';
import { Dropdown } from '@/components/commons/Dropdown';
import { useForm } from 'react-hook-form';
import { useLocalization } from '@fluent/react';
import { useLocation, useNavigate } from 'react-router-dom';

View File

@@ -1,7 +1,7 @@
import classNames from 'classnames';
import { ReactNode, useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import { useBreakpoint } from '../../hooks/breakpoint';
import { useBreakpoint } from '@/hooks/breakpoint';
export function SettingsPageLayout({
children,

View File

@@ -1,7 +1,7 @@
import classNames from 'classnames';
import { ReactNode, useMemo } from 'react';
import { NavLink, useLocation, useMatch } from 'react-router-dom';
import { Typography } from '../commons/Typography';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
export function SettingsLink({

View File

@@ -10,25 +10,26 @@ import {
ModelRatiosT,
ModelSettingsT,
ModelTogglesT,
ResetsSettingsT,
RpcMessage,
SettingsRequestT,
SettingsResponseT,
SteamVRTrackersSettingT,
TapDetectionSettingsT,
} from 'solarxr-protocol';
import { useConfig } from '../../../hooks/config';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { useLocaleConfig } from '../../../i18n/config';
import { CheckBox } from '../../commons/Checkbox';
import { SteamIcon } from '../../commons/icon/SteamIcon';
import { WrenchIcon } from '../../commons/icon/WrenchIcons';
import { NumberSelector } from '../../commons/NumberSelector';
import { Radio } from '../../commons/Radio';
import { Typography } from '../../commons/Typography';
import { useConfig } from '@/hooks/config';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { useLocaleConfig } from '@/i18n/config';
import { CheckBox } from '@/components/commons/Checkbox';
import { SteamIcon } from '@/components/commons/icon/SteamIcon';
import { WrenchIcon } from '@/components/commons/icon/WrenchIcons';
import { NumberSelector } from '@/components/commons/NumberSelector';
import { Radio } from '@/components/commons/Radio';
import { Typography } from '@/components/commons/Typography';
import {
SettingsPageLayout,
SettingsPagePaneLayout,
} from '../SettingsPageLayout';
} from '@/components/settings/SettingsPageLayout';
interface SettingsForm {
trackers: {
@@ -67,6 +68,7 @@ interface SettingsForm {
imputeHipFromWaistLegs: number;
interpHipLegs: number;
interpKneeTrackerAnkle: number;
interpKneeAnkle: number;
};
tapDetection: {
mountingResetEnabled: boolean;
@@ -83,6 +85,10 @@ interface SettingsForm {
legTweaks: {
correctionStrength: number;
};
resetsSettings: {
resetMountingFeet: boolean;
armsMountingResetMode: number;
};
}
const defaultValues = {
@@ -103,7 +109,7 @@ const defaultValues = {
skatingCorrection: false,
viveEmulation: false,
toeSnap: false,
flootPlant: true,
footPlant: true,
selfLocalization: false,
},
ratios: {
@@ -113,6 +119,7 @@ const defaultValues = {
imputeHipFromWaistLegs: 0.4,
interpHipLegs: 0.25,
interpKneeTrackerAnkle: 0.85,
interpKneeAnkle: 0.2,
},
filtering: { amount: 0.1, type: FilteringType.NONE },
driftCompensation: {
@@ -133,6 +140,10 @@ const defaultValues = {
numberTrackersOverThreshold: 1,
},
legTweaks: { correctionStrength: 0.3 },
resetsSettings: {
resetMountingFeet: false,
armsMountingResetMode: 0,
},
};
export function GeneralSettings() {
@@ -196,6 +207,7 @@ export function GeneralSettings() {
ratios.interpHipLegs = values.ratios.interpHipLegs || -1;
ratios.interpKneeTrackerAnkle =
values.ratios.interpKneeTrackerAnkle || -1;
ratios.interpKneeAnkle = values.ratios.interpKneeAnkle || -1;
modelSettings.ratios = ratios;
}
@@ -234,6 +246,15 @@ export function GeneralSettings() {
driftCompensation.maxResets = values.driftCompensation.maxResets;
settings.driftCompensation = driftCompensation;
if (values.resetsSettings) {
const resetsSettings = new ResetsSettingsT();
resetsSettings.resetMountingFeet =
values.resetsSettings.resetMountingFeet;
resetsSettings.armsMountingResetMode =
values.resetsSettings.armsMountingResetMode;
settings.resetsSettings = resetsSettings;
}
sendRPCPacket(RpcMessage.ChangeSettingsRequest, settings);
};
@@ -330,6 +351,10 @@ export function GeneralSettings() {
};
}
if (settings.resetsSettings) {
formData.resetsSettings = settings.resetsSettings;
}
reset(formData);
});
@@ -651,6 +676,24 @@ export function GeneralSettings() {
)}
/>
</div>
<div className="flex flex-col pt-2 pb-3">
<Typography color="secondary">
{l10n.getString(
'settings-general-fk_settings-leg_fk-reset_mounting_feet-description'
)}
</Typography>
</div>
<div className="grid sm:grid-cols-1 gap-3 pb-3">
<CheckBox
variant="toggle"
outlined
control={control}
name="resetsSettings.resetMountingFeet"
label={l10n.getString(
'settings-general-fk_settings-leg_fk-reset_mounting_feet'
)}
/>
</div>
<div className="flex flex-col pt-2 pb-3">
<Typography bold>
@@ -673,6 +716,58 @@ export function GeneralSettings() {
)}
/>
</div>
<Typography color="secondary">
{l10n.getString(
'settings-general-fk_settings-arm_fk-reset_mode-description'
)}
</Typography>
<div className="grid md:grid-cols-2 flex-col gap-3 pt-2">
<Radio
control={control}
name="resetsSettings.armsMountingResetMode"
label={l10n.getString(
'settings-general-fk_settings-arm_fk-back'
)}
desciption={l10n.getString(
'settings-general-fk_settings-arm_fk-back-description'
)}
value={0}
></Radio>
<Radio
control={control}
name="resetsSettings.armsMountingResetMode"
label={l10n.getString(
'settings-general-fk_settings-arm_fk-forward'
)}
desciption={l10n.getString(
'settings-general-fk_settings-arm_fk-forward-description'
)}
value={1}
></Radio>
<Radio
control={control}
name="resetsSettings.armsMountingResetMode"
label={l10n.getString(
'settings-general-fk_settings-arm_fk-tpose_up'
)}
desciption={l10n.getString(
'settings-general-fk_settings-arm_fk-tpose_up-description'
)}
value={2}
></Radio>
<Radio
control={control}
name="resetsSettings.armsMountingResetMode"
label={l10n.getString(
'settings-general-fk_settings-arm_fk-tpose_down'
)}
desciption={l10n.getString(
'settings-general-fk_settings-arm_fk-tpose_down-description'
)}
value={3}
></Radio>
</div>
{config?.debug && (
<>
<div className="flex flex-col pt-2 pb-3">
@@ -808,6 +903,19 @@ export function GeneralSettings() {
max={1.0}
step={0.05}
/>
<NumberSelector
control={control}
name="ratios.interpKneeAnkle"
label={l10n.getString(
'settings-general-fk_settings-skeleton_settings-interp_knee_ankle'
)}
valueLabelFormat={(value) =>
percentageFormat.format(value)
}
min={0.0}
max={1.0}
step={0.05}
/>
</div>
</div>

View File

@@ -1,21 +1,21 @@
import { useLocalization } from '@fluent/react';
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { CheckBox } from '../../commons/Checkbox';
import { Typography } from '../../commons/Typography';
import { CheckBox } from '@/components/commons/Checkbox';
import { Typography } from '@/components/commons/Typography';
import {
SettingsPageLayout,
SettingsPagePaneLayout,
} from '../SettingsPageLayout';
import { defaultConfig, useConfig } from '../../../hooks/config';
import { ThemeSelector } from '../../commons/ThemeSelector';
import { SquaresIcon } from '../../commons/icon/SquaresIcon';
import { NumberSelector } from '../../commons/NumberSelector';
import { useLocaleConfig } from '../../../i18n/config';
import { LangSelector } from '../../commons/LangSelector';
import { BellIcon } from '../../commons/icon/BellIcon';
import { Range } from '../../commons/Range';
import { Dropdown } from '../../commons/Dropdown';
} from '@/components/settings/SettingsPageLayout';
import { defaultConfig, useConfig } from '@/hooks/config';
import { ThemeSelector } from '@/components/commons/ThemeSelector';
import { SquaresIcon } from '@/components/commons/icon/SquaresIcon';
import { NumberSelector } from '@/components/commons/NumberSelector';
import { useLocaleConfig } from '@/i18n/config';
import { LangSelector } from '@/components/commons/LangSelector';
import { BellIcon } from '@/components/commons/icon/BellIcon';
import { Range } from '@/components/commons/Range';
import { Dropdown } from '@/components/commons/Dropdown';
interface InterfaceSettingsForm {
appearance: {

View File

@@ -9,15 +9,15 @@ import {
SettingsRequestT,
SettingsResponseT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { CheckBox } from '../../commons/Checkbox';
import { RouterIcon } from '../../commons/icon/RouterIcon';
import { Input } from '../../commons/Input';
import { Typography } from '../../commons/Typography';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { CheckBox } from '@/components/commons/Checkbox';
import { RouterIcon } from '@/components/commons/icon/RouterIcon';
import { Input } from '@/components/commons/Input';
import { Typography } from '@/components/commons/Typography';
import {
SettingsPageLayout,
SettingsPagePaneLayout,
} from '../SettingsPageLayout';
} from '@/components/settings/SettingsPageLayout';
interface OSCRouterSettingsForm {
router: {

View File

@@ -13,15 +13,15 @@ import {
SerialTrackerRebootRequestT,
SerialUpdateResponseT,
} from 'solarxr-protocol';
import { useElemSize, useLayout } from '../../../hooks/layout';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { Button } from '../../commons/Button';
import { Dropdown } from '../../commons/Dropdown';
import { Typography } from '../../commons/Typography';
import { useElemSize, useLayout } from '@/hooks/layout';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { Button } from '@/components/commons/Button';
import { Dropdown } from '@/components/commons/Dropdown';
import { Typography } from '@/components/commons/Typography';
import { Localized, useLocalization } from '@fluent/react';
import { BaseModal } from '../../commons/BaseModal';
import { WarningBox } from '../../commons/TipBox';
import { useBreakpoint } from '../../../hooks/breakpoint';
import { BaseModal } from '@/components/commons/BaseModal';
import { WarningBox } from '@/components/commons/TipBox';
import { useBreakpoint } from '@/hooks/breakpoint';
export interface SerialForm {
port: string;

View File

@@ -9,18 +9,18 @@ import {
OSCSettingsT,
VMCOSCSettingsT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { CheckBox } from '../../commons/Checkbox';
import { FileInput } from '../../commons/FileInput';
import { VMCIcon } from '../../commons/icon/VMCIcon';
import { Input } from '../../commons/Input';
import { Typography } from '../../commons/Typography';
import { magic } from '../../../utils/formatting';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { CheckBox } from '@/components/commons/Checkbox';
import { FileInput } from '@/components/commons/FileInput';
import { VMCIcon } from '@/components/commons/icon/VMCIcon';
import { Input } from '@/components/commons/Input';
import { Typography } from '@/components/commons/Typography';
import { magic } from '@/utils/formatting';
import {
SettingsPageLayout,
SettingsPagePaneLayout,
} from '../SettingsPageLayout';
import { error } from '../../../utils/logging';
} from '@/components/settings/SettingsPageLayout';
import { error } from '@/utils/logging';
interface VMCSettingsForm {
vmc: {

View File

@@ -10,15 +10,15 @@ import {
SettingsResponseT,
VRCOSCSettingsT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { CheckBox } from '../../commons/Checkbox';
import { VRCIcon } from '../../commons/icon/VRCIcon';
import { Input } from '../../commons/Input';
import { Typography } from '../../commons/Typography';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { CheckBox } from '@/components/commons/Checkbox';
import { VRCIcon } from '@/components/commons/icon/VRCIcon';
import { Input } from '@/components/commons/Input';
import { Typography } from '@/components/commons/Typography';
import {
SettingsPageLayout,
SettingsPagePaneLayout,
} from '../SettingsPageLayout';
} from '@/components/settings/SettingsPageLayout';
interface VRCOSCSettingsForm {
vrchat: {

View File

@@ -2,14 +2,14 @@ import classNames from 'classnames';
import { useForm } from 'react-hook-form';
import ReactModal from 'react-modal';
import { BodyPart } from 'solarxr-protocol';
import { Button } from '../commons/Button';
import { CheckBox } from '../commons/Checkbox';
import { Typography } from '../commons/Typography';
import { BodyAssignment } from '../onboarding/BodyAssignment';
import { Button } from '@/components/commons/Button';
import { CheckBox } from '@/components/commons/Checkbox';
import { Typography } from '@/components/commons/Typography';
import { BodyAssignment } from '@/components/onboarding/BodyAssignment';
import { useLocalization } from '@fluent/react';
import { NeckWarningModal } from '../onboarding/NeckWarningModal';
import { useChokerWarning } from '../../hooks/choker-warning';
import { useBreakpoint } from '../../hooks/breakpoint';
import { NeckWarningModal } from '@/components/onboarding/NeckWarningModal';
import { useChokerWarning } from '@/hooks/choker-warning';
import { useBreakpoint } from '@/hooks/breakpoint';
export function SingleTrackerBodyAssignmentMenu({
isOpen,

View File

@@ -1,7 +1,7 @@
import { useConfig } from '../../hooks/config';
import { useLocaleConfig } from '../../i18n/config';
import { BatteryIcon } from '../commons/icon/BatteryIcon';
import { Typography } from '../commons/Typography';
import { useConfig } from '@/hooks/config';
import { useLocaleConfig } from '@/i18n/config';
import { BatteryIcon } from '@/components/commons/icon/BatteryIcon';
import { Typography } from '@/components/commons/Typography';
export function TrackerBattery({
value,

View File

@@ -4,13 +4,13 @@ import {
TrackerDataT,
TrackerStatus as TrackerStatusEnum,
} from 'solarxr-protocol';
import { Typography } from '../commons/Typography';
import { Typography } from '@/components/commons/Typography';
import { TrackerBattery } from './TrackerBattery';
import { TrackerWifi } from './TrackerWifi';
import { TrackerStatus } from './TrackerStatus';
import classNames from 'classnames';
import { useTracker } from '../../hooks/tracker';
import { BodyPartIcon } from '../commons/BodyPartIcon';
import { useTracker } from '@/hooks/tracker';
import { BodyPartIcon } from '@/components/commons/BodyPartIcon';
function TrackerBig({
device,

View File

@@ -1,11 +1,11 @@
import classNames from 'classnames';
import { MouseEventHandler, useEffect, useMemo, useState } from 'react';
import { BodyPart, TrackerDataT } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../hooks/app';
import { useTracker } from '../../hooks/tracker';
import { Typography } from '../commons/Typography';
import { FlatDeviceTracker } from '@/hooks/app';
import { useTracker } from '@/hooks/tracker';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
import { WarningIcon } from '../commons/icon/WarningIcon';
import { WarningIcon } from '@/components/commons/icon/WarningIcon';
function Tracker({
tracker,

View File

@@ -10,24 +10,24 @@ import {
ImuType,
RpcMessage,
} from 'solarxr-protocol';
import { useDebouncedEffect } from '../../hooks/timeout';
import { useTrackerFromId } from '../../hooks/tracker';
import { useWebsocketAPI } from '../../hooks/websocket-api';
import { useDebouncedEffect } from '@/hooks/timeout';
import { useTrackerFromId } from '@/hooks/tracker';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import {
MountingOrientationDegreesToQuatT,
QuaternionFromQuatT,
rotationToQuatMap,
similarQuaternions,
} from '../../maths/quaternion';
import { ArrowLink } from '../commons/ArrowLink';
import { BodyPartIcon } from '../commons/BodyPartIcon';
import { Button } from '../commons/Button';
import { CheckBox } from '../commons/Checkbox';
import { WarningIcon } from '../commons/icon/WarningIcon';
import { Input } from '../commons/Input';
import { Typography } from '../commons/Typography';
import { MountingSelectionMenu } from '../onboarding/pages/mounting/MountingSelectionMenu';
import { IMUVisualizerWidget } from '../widgets/IMUVisualizerWidget';
} from '@/maths/quaternion';
import { ArrowLink } from '@/components/commons/ArrowLink';
import { BodyPartIcon } from '@/components/commons/BodyPartIcon';
import { Button } from '@/components/commons/Button';
import { CheckBox } from '@/components/commons/Checkbox';
import { WarningIcon } from '@/components/commons/icon/WarningIcon';
import { Input } from '@/components/commons/Input';
import { Typography } from '@/components/commons/Typography';
import { MountingSelectionMenu } from '@/components/onboarding/pages/mounting/MountingSelectionMenu';
import { IMUVisualizerWidget } from '@/components/widgets/IMUVisualizerWidget';
import { SingleTrackerBodyAssignmentMenu } from './SingleTrackerBodyAssignmentMenu';
import { TrackerCard } from './TrackerCard';
import { Quaternion } from 'three';

View File

@@ -1,7 +1,7 @@
import classNames from 'classnames';
import { useMemo } from 'react';
import { TrackerStatus as TrackerStatusEnum } from 'solarxr-protocol';
import { Typography } from '../commons/Typography';
import { Typography } from '@/components/commons/Typography';
import { useLocalization } from '@fluent/react';
const statusLabelMap: { [key: number]: string } = {

View File

@@ -1,5 +1,5 @@
import { WifiIcon } from '../commons/icon/WifiIcon';
import { Typography } from '../commons/Typography';
import { WifiIcon } from '@/components/commons/icon/WifiIcon';
import { Typography } from '@/components/commons/Typography';
export function TrackerWifi({
rssi,

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