mirror of https://github.com/wayvr-org/wayvr.git
Compare commits
163 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
cb3aa42bd9 | |
|
|
e6c5142476 | |
|
|
b02cfa446f | |
|
|
8ad055a483 | |
|
|
f13562c7dc | |
|
|
669043035e | |
|
|
77b5004541 | |
|
|
1a44b54d98 | |
|
|
cae2d7c7e2 | |
|
|
6631c004c9 | |
|
|
98f800c644 | |
|
|
3ae01f59d1 | |
|
|
6fa434af46 | |
|
|
dcb01fdb6a | |
|
|
3940e8b4f2 | |
|
|
97418111fb | |
|
|
38590d9cfb | |
|
|
2e07818072 | |
|
|
5a9133c497 | |
|
|
84068ca710 | |
|
|
a7ff06f38a | |
|
|
7b8fadfaf2 | |
|
|
eb2786311a | |
|
|
8e0f27f690 | |
|
|
e64fb789c7 | |
|
|
05aac47716 | |
|
|
ebb912db68 | |
|
|
75154d8375 | |
|
|
4c918b0aaf | |
|
|
5ba7d1fdad | |
|
|
4eeb0afb0b | |
|
|
f4523f3ab1 | |
|
|
c594f6bda3 | |
|
|
6edf144aee | |
|
|
b85077b559 | |
|
|
29c5800a61 | |
|
|
3cfbafa577 | |
|
|
05708813be | |
|
|
4ad6287efc | |
|
|
98d8a3138d | |
|
|
7261f7fa1f | |
|
|
7efc4bb0fc | |
|
|
395e9d1919 | |
|
|
deccbda473 | |
|
|
7ff096c9ab | |
|
|
6f6f9af983 | |
|
|
6b22e4aef1 | |
|
|
707e3a4927 | |
|
|
0b4c59f1c7 | |
|
|
d1f2995846 | |
|
|
2574784ad3 | |
|
|
239337ae76 | |
|
|
67877d6a5f | |
|
|
44b7a2a6ab | |
|
|
5dffbb9fdb | |
|
|
c92e27dcf9 | |
|
|
e40b953e5a | |
|
|
9b336535f7 | |
|
|
48da2ca416 | |
|
|
b4e2fd782c | |
|
|
0613f94be6 | |
|
|
b82f781757 | |
|
|
4e4d552bb6 | |
|
|
078055dc0f | |
|
|
d56c181e9d | |
|
|
6a6264347b | |
|
|
590980e560 | |
|
|
ca550f356b | |
|
|
cf6bfe855e | |
|
|
43a435aa89 | |
|
|
2ab3605116 | |
|
|
bc19afad34 | |
|
|
e3829fdebf | |
|
|
f711d9a464 | |
|
|
302cd14a50 | |
|
|
58dbb1e1b2 | |
|
|
73ae2b7274 | |
|
|
c295bf4f0d | |
|
|
5c158e0353 | |
|
|
7f6caca0f8 | |
|
|
e1fb392297 | |
|
|
8adff4ca6a | |
|
|
629de4c8ff | |
|
|
beae8e82f5 | |
|
|
a12d1ff8f4 | |
|
|
447d75acef | |
|
|
4652f708b0 | |
|
|
e1879ca891 | |
|
|
786660a4d5 | |
|
|
9e43b9b3ad | |
|
|
7c16748f88 | |
|
|
a29451ceaa | |
|
|
d93b74cc8a | |
|
|
2def8c3a6d | |
|
|
30d786eaa1 | |
|
|
779baaf86c | |
|
|
7c7e7edbfb | |
|
|
b1e09910a2 | |
|
|
5407e53700 | |
|
|
e895a61ea0 | |
|
|
4ed52f0214 | |
|
|
fcc84e56b3 | |
|
|
c74c51f7cd | |
|
|
acaabead52 | |
|
|
fd8a327395 | |
|
|
952b6e10b6 | |
|
|
245666ab06 | |
|
|
227e3851bc | |
|
|
4e9b893304 | |
|
|
d311813899 | |
|
|
075a6dd63b | |
|
|
83b9a1920f | |
|
|
635cfef63e | |
|
|
a8262c1de4 | |
|
|
a3e3101ab0 | |
|
|
28442ac6a8 | |
|
|
d6268c0c20 | |
|
|
5c0ae395a2 | |
|
|
962ed32452 | |
|
|
f3438b1867 | |
|
|
e0ab4be8e3 | |
|
|
c4655b7b9a | |
|
|
c32e3ef86e | |
|
|
2ea3b222f3 | |
|
|
6f5be3a157 | |
|
|
db436d4630 | |
|
|
895e95dcf4 | |
|
|
0516270dcb | |
|
|
28a9ed2c27 | |
|
|
b1fb0d9347 | |
|
|
031157ea8c | |
|
|
6a064248dc | |
|
|
7ab47ada4b | |
|
|
1febd4ed0d | |
|
|
f2e2c37108 | |
|
|
b3e4e37992 | |
|
|
fb71975019 | |
|
|
02f1de59b2 | |
|
|
40430ea94e | |
|
|
867c343c9b | |
|
|
2e7a528857 | |
|
|
0a7f8340d7 | |
|
|
e79dfcb719 | |
|
|
cb99676230 | |
|
|
bc0fad60d5 | |
|
|
3d2689c931 | |
|
|
dc58c1a555 | |
|
|
a4ce23881a | |
|
|
62c210fc1d | |
|
|
c3cbc43f6f | |
|
|
155340b78d | |
|
|
d7bd243c41 | |
|
|
3c7e91c28c | |
|
|
a00f2ab8db | |
|
|
b83c54334f | |
|
|
f3dc87fa64 | |
|
|
9f854d0649 | |
|
|
000bc3c166 | |
|
|
1820e2b152 | |
|
|
a10b20aea9 | |
|
|
80237d36cd | |
|
|
cfeef62215 | |
|
|
730b546e84 |
|
|
@ -29,6 +29,9 @@ jobs:
|
||||||
- name: Cargo Build
|
- name: Cargo Build
|
||||||
run: |
|
run: |
|
||||||
../.github/workflows/scripts/appimage_build_wlx.sh
|
../.github/workflows/scripts/appimage_build_wlx.sh
|
||||||
|
- name: Build xwayland-satellite
|
||||||
|
run: |
|
||||||
|
../.github/workflows/scripts/appimage_build_satellite.sh
|
||||||
- name: Package AppImage
|
- name: Package AppImage
|
||||||
run: |
|
run: |
|
||||||
../.github/workflows/scripts/appimage_package.sh
|
../.github/workflows/scripts/appimage_package.sh
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ jobs:
|
||||||
- name: Cargo Build
|
- name: Cargo Build
|
||||||
run: |
|
run: |
|
||||||
../.github/workflows/scripts/appimage_build_wlx.sh
|
../.github/workflows/scripts/appimage_build_wlx.sh
|
||||||
|
- name: Build xwayland-satellite
|
||||||
|
run: |
|
||||||
|
../.github/workflows/scripts/appimage_build_satellite.sh
|
||||||
- name: Package AppImage
|
- name: Package AppImage
|
||||||
run: |
|
run: |
|
||||||
../.github/workflows/scripts/appimage_package.sh
|
../.github/workflows/scripts/appimage_package.sh
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
sudo apt install \
|
||||||
|
xwayland \
|
||||||
|
libxcb1-dev \
|
||||||
|
libxcb-cursor-dev \
|
||||||
|
clang \
|
||||||
|
pkg-config
|
||||||
|
|
||||||
|
git clone https://github.com/Supreeeme/xwayland-satellite.git
|
||||||
|
cd xwayland-satellite
|
||||||
|
|
||||||
|
cargo build --release
|
||||||
|
chmod +x ../target/release/xwayland-satellite
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cp xwayland-satellite/target/release/xwayland-satellite ${APPDIR}/usr/bin
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1 libwayland-dev libegl-dev libxcb-glx0 libxcb-glx0-dev dav1d libdav1d-dev libvulkan-dev glslc vulkan-tools
|
sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev \
|
||||||
|
libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 \
|
||||||
|
libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1 libwayland-dev libegl-dev libxcb-glx0 libxcb-glx0-dev \
|
||||||
|
dav1d libdav1d-dev libvulkan-dev glslc vulkan-tools libudev-dev libudev1 libinput-dev libinput10
|
||||||
|
|
||||||
rustup update
|
rustup update
|
||||||
|
|
||||||
if [ "$APPDIR" != "" ]; then
|
if [ "$APPDIR" != "" ]; then
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.~lock.*
|
||||||
/target
|
/target
|
||||||
.gdb_history
|
.gdb_history
|
||||||
.vscode
|
.vscode
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
24
Cargo.toml
24
Cargo.toml
|
|
@ -14,11 +14,17 @@ members = [
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.100"
|
anyhow = "1.0.100"
|
||||||
|
async-channel = "2.3"
|
||||||
|
async-io = "2.1"
|
||||||
bytes = { version = "1.11.1" }
|
bytes = { version = "1.11.1" }
|
||||||
|
chrono = "0.4.42"
|
||||||
clap = { version = "4.5.53", features = ["derive"] }
|
clap = { version = "4.5.53", features = ["derive"] }
|
||||||
|
dbus = { version = "0.9.12" }
|
||||||
glam = { version = "0.30.9", features = ["mint", "serde"] }
|
glam = { version = "0.30.9", features = ["mint", "serde"] }
|
||||||
idmap = "0.2.2"
|
idmap = "0.2.2"
|
||||||
idmap-derive = "0.2.22"
|
idmap-derive = "0.2.22"
|
||||||
|
interprocess = { version = "2.2.3" }
|
||||||
|
libc = "0.2.178"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
pipewire = { version = "0.10", features = ["v0_3_33", "v0_3_65"] }
|
pipewire = { version = "0.10", features = ["v0_3_33", "v0_3_65"] }
|
||||||
regex = "1.12.2"
|
regex = "1.12.2"
|
||||||
|
|
@ -27,20 +33,30 @@ serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1.0.145"
|
serde_json = "1.0.145"
|
||||||
serde_json5 = "0.2.1"
|
serde_json5 = "0.2.1"
|
||||||
slotmap = "1.1.1"
|
slotmap = "1.1.1"
|
||||||
|
smallvec = "1.15.2"
|
||||||
smol = "2.0.2"
|
smol = "2.0.2"
|
||||||
strum = { version = "0.27.2", features = ["derive"] }
|
strum = { version = "0.27.2", features = ["derive"] }
|
||||||
|
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
||||||
uuid = { version = "1.19.0", features = ["fast-rng", "serde", "v4"] }
|
uuid = { version = "1.19.0", features = ["fast-rng", "serde", "v4"] }
|
||||||
vulkano = { version = "0.35.2", default-features = false, features = [
|
vulkano = {
|
||||||
"macros",
|
version = "0.35.2",
|
||||||
] }
|
default-features = false,
|
||||||
|
features = [
|
||||||
|
"macros",
|
||||||
|
]
|
||||||
|
}
|
||||||
vulkano-shaders = "0.35.0"
|
vulkano-shaders = "0.35.0"
|
||||||
wayland-client = { version = "0.31" }
|
wayland-client = { version = "0.31" }
|
||||||
wayland-protocols = { version = "0.32" }
|
wayland-protocols = { version = "0.32" }
|
||||||
wayland-protocols-misc = { version = "0.3.12" }
|
wayland-protocols-misc = { version = "0.3.12" }
|
||||||
|
winit = "0.30.12"
|
||||||
xdg = "3.0.0"
|
xdg = "3.0.0"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
vulkano = { git = "https://github.com/galister/vulkano.git", rev = "cf7f92867928a56ce16b376037c1120f2b167678" }
|
vulkano = {
|
||||||
|
git = "https://github.com/galister/vulkano.git",
|
||||||
|
rev = "cf7f92867928a56ce16b376037c1120f2b167678"
|
||||||
|
}
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 1
|
opt-level = 1
|
||||||
|
|
|
||||||
62
README.md
62
README.md
|
|
@ -62,13 +62,12 @@ In case screens were selected in the wrong order:
|
||||||
|
|
||||||
**WiVRn users**: Select WayVR from the `Application` drop-down. If there's no such entry, select `Custom` and browse to your WayVR executable or AppImage.
|
**WiVRn users**: Select WayVR from the `Application` drop-down. If there's no such entry, select `Custom` and browse to your WayVR executable or AppImage.
|
||||||
|
|
||||||
**Envision users**: Go to the Plugins menu and select the WayVR plugin. This will download and run the AppImage version of the overlay.
|
**Envision users**: Go to the Plugins menu and toggle on the WayVR plugin. If WayVR isn't in the Plugins list, or the list is empty, ensure you've installed WayVR fully, such that it appears in your Desktop Environment's application menu. If you've *downloaded* the WayVR AppImage, [Gear Lever](https://github.com/mijorus/gearlever) can *install* it, which creates the application menu entry.
|
||||||
To run a standalone installation (for instance, from the AUR), create a bash script containing `wayvr --openxr --show` and then set this bash script as a custom Envision plugin.
|
|
||||||
|
**SteamVR users**: WayVR no longer registers itself for auto-start, due to bugs in SteamVR. For now, you must start WayVR manually.
|
||||||
|
|
||||||
This will show a home environment with headset passthrough enabled by default or a [customizable background](https://wayvr.org/docs/various/openxr-skybox/)!
|
This will show a home environment with headset passthrough enabled by default or a [customizable background](https://wayvr.org/docs/various/openxr-skybox/)!
|
||||||
|
|
||||||
**SteamVR users**: WayVR will register itself for auto-start, so there is no need to start it every time. Disclaimer: SteamVR will sometimes disregard this and not start WayVR anyway.
|
|
||||||
|
|
||||||
**Please continue reading the guide below.**
|
**Please continue reading the guide below.**
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
@ -84,7 +83,9 @@ Show and hide the working set using:
|
||||||
- Non-vive controller: double-tap B or Y on the left controller.
|
- Non-vive controller: double-tap B or Y on the left controller.
|
||||||
- Vive controller: double-tap the menu button on the left controller (for SteamVR, the `showhide` binding must be bound)
|
- Vive controller: double-tap the menu button on the left controller (for SteamVR, the `showhide` binding must be bound)
|
||||||
|
|
||||||
See the [bindings](#default-bindings) section on how to grab, move and resize overlay windows.
|
Moving overlays: Grab + Joystick
|
||||||
|
|
||||||
|
Resizing overlays: Grab + Click + Joystick
|
||||||
|
|
||||||
### Pointer Modes AKA Laser Colors
|
### Pointer Modes AKA Laser Colors
|
||||||
|
|
||||||
|
|
@ -99,20 +100,29 @@ Please see the bindings section below on how to activate these modes.
|
||||||
|
|
||||||
The guide here uses the colors for ease of getting started.
|
The guide here uses the colors for ease of getting started.
|
||||||
|
|
||||||
|
### Edit mode
|
||||||
|
|
||||||
|
Ways to enter Edit mode:
|
||||||
|
- Edit mode button on Watch face
|
||||||
|
- Taskbar (top of keyboard) hamburger menu
|
||||||
|
- Edit mode button on the title bar of WayVR apps (next to X button)
|
||||||
|
|
||||||
|
Edit mode lets you grab overlays and reposition them in yourset.
|
||||||
|
|
||||||
|
It's also possible to change overlay behavior and tweak your overlays in different way.
|
||||||
|
|
||||||
|
While in edit mode, try hovering over various overlays to see their options!
|
||||||
|
|
||||||
### The watch
|
### The watch
|
||||||
|
|
||||||
Check your left wrist for the watch. The watch is the primary tool for controlling the app.
|
Check your left wrist for the watch. The watch is the primary tool for controlling the app.
|
||||||
|
|
||||||
The top of the watch shows device batteries, and the bottom shows your overlay controls.
|
The top of the watch shows device batteries, and the bottom shows your overlay controls.
|
||||||
|
|
||||||
Enter edit mode (the leftmost button at the bottom) to edit your overlay sets.
|
|
||||||
|
|
||||||
While in edit mode, the watch can also be grabbed and passed between your hands.
|
While in edit mode, the watch can also be grabbed and passed between your hands.
|
||||||
|
|
||||||
After grabbing, the watch will automatically attach to the hand that's opposite from the one that held it.
|
After grabbing, the watch will automatically attach to the hand that's opposite from the one that held it.
|
||||||
|
|
||||||
In edit mode, try hovering over other overlays to see their advanced options!
|
|
||||||
|
|
||||||
### The screens
|
### The screens
|
||||||
|
|
||||||
Hovering a pointer over a screen will move the mouse. If more than one pointer is hovering over a screen, the pointer that was last used to click will take precedence.
|
Hovering a pointer over a screen will move the mouse. If more than one pointer is hovering over a screen, the pointer that was last used to click will take precedence.
|
||||||
|
|
@ -126,6 +136,10 @@ The click type depends on the laser color:
|
||||||
|
|
||||||
### The keyboard
|
### The keyboard
|
||||||
|
|
||||||
|
The keyboard sends keys to the screen or WayVR application with the most recent mouse interaction.
|
||||||
|
|
||||||
|
On top of the keyboard is the taskbar, which lists WayVR apps as well as screens, mirrors and panels overlays.
|
||||||
|
|
||||||
Typing
|
Typing
|
||||||
|
|
||||||
- Use the BLUE laser when typing regularly.
|
- Use the BLUE laser when typing regularly.
|
||||||
|
|
@ -146,12 +160,9 @@ Typing
|
||||||
|
|
||||||
### Changing Bindings
|
### Changing Bindings
|
||||||
|
|
||||||
SteamVR: Simply change the bindings from the SteamVR bindings section. If WayVR doesn't show up on the list, select any other title and then press back on the top left. (SteamVR is weird like that sometimes)
|
- SteamVR: Simply change the bindings from the SteamVR bindings section.
|
||||||
|
- If WayVR doesn't show up on the list, select any other title and then press back on the top left. (SteamVR bug)
|
||||||
OpenXR (Monado/WiVRn): See [Docs: OpenXR Bindings](https://wayvr.org/docs/various/openxr-bindings/)
|
- Monado/WiVRn: See WayVR Dashboard → Settings → Controls.
|
||||||
|
|
||||||
If your controllers are not supported, please reach out. \
|
|
||||||
We would like to work with you and include additional bindings.
|
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
|
|
@ -171,14 +182,16 @@ Check [here](https://wayvr.org/docs/various/troubleshooting/) for tips.
|
||||||
|
|
||||||
## Known Issues
|
## Known Issues
|
||||||
|
|
||||||
### Mouse is not where it should be
|
### Mouse movement is wrong
|
||||||
|
|
||||||
If the mouse is moving on a completely different screen, the screens were likely selected in the wrong order:
|
**If the mouse is moving on a completely different screen**, the screens were likely selected in the wrong order:
|
||||||
|
|
||||||
- Go to Settings and press `Clear PipeWire tokens` and then `Restart software`
|
- Go to Settings and press `Clear PipeWire tokens` and then `Restart software`
|
||||||
- Pay attention to your notifications, which tell you in which order to pick the screens.
|
- Pay attention to your notifications, which tell you in which order to pick the screens.
|
||||||
- If notifications don't show, try starting WayVR from the terminal and look for instructions in there.
|
- If notifications don't show, try starting WayVR from the terminal and look for instructions in there.
|
||||||
|
|
||||||
|
**If the mouse is on the correct screen but moves in weird ways**, enter Edit Mode, hover the screen and under Mouse Fixes, select the mode that works.
|
||||||
|
|
||||||
COSMIC desktop:
|
COSMIC desktop:
|
||||||
|
|
||||||
- Due to limitations with COSMIC, the mouse can only move on a single display.
|
- Due to limitations with COSMIC, the mouse can only move on a single display.
|
||||||
|
|
@ -189,19 +202,12 @@ X11 users:
|
||||||
- DPI scaling is not supported and will mess with the mouse.
|
- DPI scaling is not supported and will mess with the mouse.
|
||||||
- Upright screens are not supported and will mess with the mouse.
|
- Upright screens are not supported and will mess with the mouse.
|
||||||
|
|
||||||
### Screens are blank or black or frozen on SteamVR 2.14+
|
### Screens or launched apps don't work when auto-started by SteamVR or WiVRn
|
||||||
|
|
||||||
As of SteamVR version 2.14.x, PipeWire capture no longer works when using Steam Link.
|
SteamVR starts WayVR in the Steam runtime, and systemd/flatpak WiVRn can also start WayVR in a sub-optimal environment.
|
||||||
|
|
||||||
We're unable to completely troubleshoot how and why SteamVR interferes with PipeWire, so consider the following workarounds for the time being:
|
The easiest fix is to start WayVR separately. It's possible to start WayVR before starting SteamVR/WiVRn by passing `--wait`:
|
||||||
|
- `wayvr --wait` or `/path/to/WayVR.AppImage --wait`
|
||||||
- Use another streamer, such as WiVRn or ALVR. Note that SteamVR on Linux is considered experimental by Valve themselves [disclaimer](https://github.com/ValveSoftware/SteamVR-for-Linux?tab=readme-ov-file#steamvr-release-notes-and-known-issues).
|
|
||||||
- If your desktop [supports ScreenCopy](https://wayland.app/protocols/wlr-screencopy-unstable-v1#compositor-support), go to Settings and set `Wayland capture method` to `ScreenCopy`
|
|
||||||
- If your desktop has an X11 mode, try using that
|
|
||||||
|
|
||||||
### Modifiers get stuck
|
|
||||||
|
|
||||||
Hiding the keyboard will unpress all of its buttons. Alternatively, go to Settings and use the `Restart software` button.
|
|
||||||
|
|
||||||
### X11 limitations
|
### X11 limitations
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,27 +8,27 @@ authors = ["galister", "oo8dev"]
|
||||||
repository = "https://github.com/wlx-team/wayvr"
|
repository = "https://github.com/wlx-team/wayvr"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
|
||||||
|
wgui = { path = "../wgui/" }
|
||||||
|
wlx-common = { path = "../wlx-common" }
|
||||||
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
async-native-tls = "0.5.0"
|
chrono.workspace = true
|
||||||
chrono = "0.4.42"
|
|
||||||
glam = { workspace = true, features = ["mint", "serde"] }
|
glam = { workspace = true, features = ["mint", "serde"] }
|
||||||
http-body-util = "0.1.3"
|
|
||||||
hyper = { version = "1.8.1", features = ["client", "http1", "http2"] }
|
|
||||||
keyvalues-parser = { git = "https://codeberg.org/CosmicHarper/vdf-rs.git", rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145" }
|
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
lz4_flex = { version = "0.13.1", features = ["frame"] }
|
|
||||||
rust-embed.workspace = true
|
rust-embed.workspace = true
|
||||||
serde = { workspace = true, features = ["rc"] }
|
serde = { workspace = true, features = ["rc"] }
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
smol = { workspace = true }
|
smol = { workspace = true }
|
||||||
smol-hyper = "0.1.1"
|
|
||||||
strum.workspace = true
|
strum.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
|
|
||||||
wgui = { path = "../wgui/" }
|
|
||||||
wlx-common = { path = "../wlx-common" }
|
|
||||||
xdg.workspace = true
|
xdg.workspace = true
|
||||||
|
|
||||||
|
keyvalues-parser = "0.2.4"
|
||||||
|
lz4_flex = { version = "0.13.1", features = ["frame"] }
|
||||||
|
ureq = "3.3.0"
|
||||||
|
rand = "0.10.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["monado"]
|
default = ["monado"]
|
||||||
monado = []
|
monado = []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="M15 14v-2h8v2zm-4 7l-3.175-2.85q-1.8-1.625-3.088-2.9t-2.125-2.4t-1.225-2.175T1 8.475q0-2.35 1.575-3.912T6.5 3q1.3 0 2.475.538T11 5.075q.85-1 2.025-1.537T15.5 3q2.125 0 3.563 1.288T20.85 7.3q-.45-.175-.9-.262t-.875-.088q-2.525 0-4.3 1.763T13 13q0 1.3.525 2.463T15 17.45q-.475.425-1.237 1.088T12.45 19.7z"/></svg>
|
||||||
|
After Width: | Height: | Size: 538 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="M18.288 16.713Q18 16.425 18 16v-2h-2q-.425 0-.712-.288T15 13t.288-.712T16 12h2v-2q0-.425.288-.712T19 9t.713.288T20 10v2h2q.425 0 .713.288T23 13t-.288.713T22 14h-2v2q0 .425-.288.713T19 17t-.712-.288M1.75 23.626v-3.8zM10.3 20.2q-.35-.125-.625-.4q-1.1-1-2.6-2.275t-2.85-2.737t-2.287-3.063T1 8.475q0-2.35 1.575-3.912T6.5 3q1.3 0 2.475.538T11 5.075q.85-1 2.025-1.537T15.5 3q1.575 0 2.788.738T20.2 5.6q.275.475-.087.963T19.075 7h-.4q-2.125 0-3.9 1.713T13 13q0 1.05.338 1.988T14.4 16.7q.275.3.238.7t-.338.675l-1.975 1.75q-.275.275-.625.388t-.7.112t-.7-.125"/></svg>
|
||||||
|
After Width: | Height: | Size: 785 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE --><path fill="currentColor" d="M14.94 19.5L12 17.77L9.06 19.5l.78-3.34l-2.59-2.24l3.41-.29L12 10.5l1.34 3.13l3.41.29l-2.59 2.24M20 2H4v2l4.86 3.64a8 8 0 1 0 6.28 0L20 4m-2 11a6 6 0 1 1-7.18-5.88a5.9 5.9 0 0 1 2.36 0A6 6 0 0 1 18 15m-5.37-8h-1.26l-4-3h9.34Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 470 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="M9.175 10.825Q8 9.65 8 8t1.175-2.825T12 4t2.825 1.175T16 8t-1.175 2.825T12 12t-2.825-1.175M4 20v-2.8q0-.85.438-1.562T5.6 14.55q1.55-.775 3.15-1.162T12 13t3.25.388t3.15 1.162q.725.375 1.163 1.088T20 17.2V20z"/></svg>
|
||||||
|
After Width: | Height: | Size: 442 B |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
|
|
@ -1,6 +1,4 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="theme.xml" />
|
|
||||||
|
|
||||||
<theme>
|
<theme>
|
||||||
<var key="side_size" value="48" />
|
<var key="side_size" value="48" />
|
||||||
<var key="top_size" value="40" />
|
<var key="top_size" value="40" />
|
||||||
|
|
@ -14,10 +12,8 @@
|
||||||
round="100%"
|
round="100%"
|
||||||
width="~side_button_size"
|
width="~side_button_size"
|
||||||
height="~side_button_size"
|
height="~side_button_size"
|
||||||
color="#44444400"
|
color="background_contrast(transparent)"
|
||||||
hover_color="#333333ff"
|
border_color="background_contrast"
|
||||||
border_color="#00000000"
|
|
||||||
hover_border_color="#555555ff"
|
|
||||||
tooltip="${tooltip}"
|
tooltip="${tooltip}"
|
||||||
tooltip_side="${tooltip_side}"
|
tooltip_side="${tooltip_side}"
|
||||||
>
|
>
|
||||||
|
|
@ -39,7 +35,7 @@
|
||||||
<rectangle
|
<rectangle
|
||||||
width="100%"
|
width="100%"
|
||||||
round="100%"
|
round="100%"
|
||||||
color="~color_menu_dark"
|
color="background_contrast"
|
||||||
flex_direction="column"
|
flex_direction="column"
|
||||||
justify_content="center"
|
justify_content="center"
|
||||||
align_items="center"
|
align_items="center"
|
||||||
|
|
@ -49,7 +45,7 @@
|
||||||
<SideButton id="btn_side_apps" src_builtin="dashboard/apps.svg" tooltip="APPLICATIONS" tooltip_side="right" />
|
<SideButton id="btn_side_apps" src_builtin="dashboard/apps.svg" tooltip="APPLICATIONS" tooltip_side="right" />
|
||||||
<SideButton id="btn_side_games" src_builtin="dashboard/games.svg" tooltip="GAMES" tooltip_side="right" />
|
<SideButton id="btn_side_games" src_builtin="dashboard/games.svg" tooltip="GAMES" tooltip_side="right" />
|
||||||
<SideButton id="btn_side_monado" src_builtin="dashboard/monado.svg" tooltip="MONADO_RUNTIME" tooltip_side="right" />
|
<SideButton id="btn_side_monado" src_builtin="dashboard/monado.svg" tooltip="MONADO_RUNTIME" tooltip_side="right" />
|
||||||
<rectangle height="2" color="#FFFFFF33" width="~side_sprite_size" />
|
<rectangle height="2" color="outline" width="~side_sprite_size" />
|
||||||
<SideButton id="btn_side_settings" src_builtin="dashboard/settings.svg" tooltip="SETTINGS" tooltip_side="right" />
|
<SideButton id="btn_side_settings" src_builtin="dashboard/settings.svg" tooltip="SETTINGS" tooltip_side="right" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -65,13 +61,14 @@
|
||||||
<div position="relative" width="100%" height="~top_size" min_height="~top_size" max_height="~top_size" justify_content="end">
|
<div position="relative" width="100%" height="~top_size" min_height="~top_size" max_height="~top_size" justify_content="end">
|
||||||
<!-- Title bar -->
|
<!-- Title bar -->
|
||||||
<div width="100%" align_items="center" justify_content="center">
|
<div width="100%" align_items="center" justify_content="center">
|
||||||
<rectangle min_width="300" height="100%" consume_mouse_events="1" round="100%" color="~color_top_panel" align_items="center" justify_content="center" gap="8">
|
<rectangle min_width="300" height="100%" consume_mouse_events="1" round="100%" color="background_contrast" align_items="center" justify_content="center" gap="8">
|
||||||
<sprite id="sprite_titlebar_icon" width="24" height="24" />
|
<sprite id="sprite_titlebar_icon" width="24" height="24" color="on_background_contrast" />
|
||||||
<label id="label_titlebar_title" weight="bold" size="16" text="Title" />
|
<label id="label_titlebar_title" weight="bold" size="16" text="Title" color="on_background_contrast" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
<!-- Close button -->
|
<!-- Close button -->
|
||||||
<Button position="absolute" id="btn_close" color="~color_top_panel" round="100%" width="~top_size" height="~top_size" tooltip="CLOSE_WINDOW" tooltip_side="left">
|
<Button position="absolute" id="btn_close" color="background_contrast" border_color="background_contrast" round="100%" width="~top_size" height="~top_size" tooltip="CLOSE_WINDOW" tooltip_side="left"
|
||||||
|
hover_color="danger" hover_border_color="danger(rgb-mult-0.5)" >
|
||||||
<sprite src_builtin="dashboard/close.svg" width="32" height="32" />
|
<sprite src_builtin="dashboard/close.svg" width="32" height="32" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -80,8 +77,8 @@
|
||||||
<!-- color and color2 alpha will be modified at runtime -->
|
<!-- color and color2 alpha will be modified at runtime -->
|
||||||
<rectangle
|
<rectangle
|
||||||
id="rect_content"
|
id="rect_content"
|
||||||
color2="#0d131a00"
|
color2="background_contrast"
|
||||||
color="#252f5300"
|
color="background"
|
||||||
gradient="vertical"
|
gradient="vertical"
|
||||||
round="8"
|
round="8"
|
||||||
flex_grow="1"
|
flex_grow="1"
|
||||||
|
|
@ -92,7 +89,7 @@
|
||||||
<!-- radial gradient -->
|
<!-- radial gradient -->
|
||||||
<rectangle
|
<rectangle
|
||||||
position="absolute" width="100%" height="100%"
|
position="absolute" width="100%" height="100%"
|
||||||
gradient="radial" color="#44BBFF11" color2="#00000000" />
|
gradient="radial" color="background_variant(opacity-0.5)" color2="background_variant(transparent)" />
|
||||||
|
|
||||||
<div overflow_x="scroll" overflow_y="scroll" width="100%" height="100%">
|
<div overflow_x="scroll" overflow_y="scroll" width="100%" height="100%">
|
||||||
<div
|
<div
|
||||||
|
|
@ -120,36 +117,36 @@
|
||||||
flex_direction="row"
|
flex_direction="row"
|
||||||
align_items="center"
|
align_items="center"
|
||||||
justify_content="space_between"
|
justify_content="space_between"
|
||||||
color="~color_bottom_panel"
|
color="background"
|
||||||
>
|
>
|
||||||
<!-- left gradient -->
|
<!-- left gradient -->
|
||||||
<div position="absolute" width="100%" height="100%" justify_content="start">
|
<div position="absolute" width="100%" height="100%" justify_content="start">
|
||||||
<rectangle position="absolute" width="40%" height="100%" color="#0a0a0a" color2="#0a0a0a00" round="8" gradient="horizontal" />
|
<rectangle position="absolute" width="40%" height="100%" color="shadow" color2="shadow(transparent)" round="8" gradient="horizontal" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- right gradient -->
|
<!-- right gradient -->
|
||||||
<div position="absolute" width="100%" height="100%" justify_content="end">
|
<div position="absolute" width="100%" height="100%" justify_content="end">
|
||||||
<rectangle position="absolute" width="40%" height="100%" color2="#0a0a0a" color="#0a0a0a00" round="8" gradient="horizontal" />
|
<rectangle position="absolute" width="40%" height="100%" color2="shadow" color="shadow(transparent)" round="8" gradient="horizontal" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- top shine -->
|
<!-- top shine -->
|
||||||
<div position="absolute" width="100%" height="100%" justify_content="center">
|
<div position="absolute" width="100%" height="100%" justify_content="center">
|
||||||
<rectangle position="absolute" width="99%" height="2" color="#FFFFFF22" round="4" />
|
<rectangle position="absolute" width="99%" height="2" color="highlight(opacity-0.2)" round="4" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Left bottom side -->
|
<!-- Left bottom side -->
|
||||||
<div margin_left="8">
|
<div margin_left="8">
|
||||||
<Button id="btn_audio" color="#FFFFFF00" border_color="#FFFFFF00" tooltip="AUDIO.VOLUME" tooltip_side="top">
|
<Button id="btn_audio" color="background(transparent)" border_color="background(transparent)" tooltip="AUDIO.VOLUME" tooltip_side="top">
|
||||||
<sprite src_builtin="dashboard/volume.svg" width="24" height="24" margin="8" />
|
<sprite src_builtin="dashboard/volume.svg" width="24" height="24" margin="8" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button id="btn_recenter" color="#FFFFFF00" border_color="#FFFFFF00" tooltip="ACTIONS.RECENTER_PLAYSPACE" tooltip_side="top">
|
<Button id="btn_recenter" color="background(transparent)" border_color="background(transparent)" tooltip="ACTIONS.RECENTER_PLAYSPACE" tooltip_side="top">
|
||||||
<sprite src_builtin="dashboard/recenter.svg" width="24" height="24" margin="8" />
|
<sprite src_builtin="dashboard/recenter.svg" width="24" height="24" margin="8" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right bottom side -->
|
<!-- Right bottom side -->
|
||||||
<div margin_right="16">
|
<div margin_right="16">
|
||||||
<label id="label_time" size="16" weight="light" />
|
<label id="label_time" weight="bold" size="16" color="on_background" />
|
||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="theme.xml" />
|
|
||||||
|
|
||||||
<macro name="dropdown_button"
|
<macro name="dropdown_button"
|
||||||
flex_direction="row"
|
flex_direction="row"
|
||||||
border="2"
|
border="2"
|
||||||
color="#00000055"
|
color="background"
|
||||||
border_color="#FFFFFF66"
|
border_color="outline"
|
||||||
justify_content="space_between" />
|
justify_content="space_between" />
|
||||||
|
|
||||||
<!-- id, text, translation, tooltip, min_width -->
|
<!-- id, text, translation, tooltip, min_width -->
|
||||||
|
|
@ -17,9 +15,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div gap="2">
|
<div gap="2">
|
||||||
<div padding_top="4" padding_bottom="4">
|
<div padding_top="4" padding_bottom="4">
|
||||||
<rectangle width="2" height="100%" color="#FFFFFF1A" />
|
<rectangle width="2" height="100%" color="outline" />
|
||||||
</div>
|
</div>
|
||||||
<sprite margin_left="-4" width="30" height="30" color="~color_text" src_builtin="dashboard/down.svg" />
|
<sprite margin_left="-4" width="30" height="30" src_builtin="dashboard/down.svg" />
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="theme.xml" />
|
|
||||||
|
|
||||||
<macro name="group_box"
|
<macro name="group_box"
|
||||||
flex_direction="column"
|
flex_direction="column"
|
||||||
align_items="baseline"
|
align_items="baseline"
|
||||||
border="2"
|
border="2"
|
||||||
color="#00000055"
|
color="background_contrast(opacity-0.5)"
|
||||||
border_color="#FFFFFF66"
|
border_color="outline"
|
||||||
padding="12"
|
padding="12"
|
||||||
gap="8"
|
gap="8"
|
||||||
round="8" />
|
round="8" />
|
||||||
|
|
@ -14,9 +12,9 @@
|
||||||
<!-- src_builtin, text, translation -->
|
<!-- src_builtin, text, translation -->
|
||||||
<template name="GroupBoxTitle">
|
<template name="GroupBoxTitle">
|
||||||
<div flex_direction="row" align_items="center" gap="8">
|
<div flex_direction="row" align_items="center" gap="8">
|
||||||
<sprite src_builtin="${src_builtin}" width="24" height="24" />
|
<sprite src_builtin="${src_builtin}" width="24" height="24" color="secondary" />
|
||||||
<label text="${text}" translation="${translation}" weight="bold" size="18" />
|
<label text="${text}" translation="${translation}" weight="bold" size="18" color="secondary" />
|
||||||
</div>
|
</div>
|
||||||
<rectangle color="#FFFFFF44" width="100%" height="2" />
|
<rectangle color="outline" width="100%" height="2" />
|
||||||
</template>
|
</template>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<template name="LoadingWithText">
|
<template name="LoadingWithText">
|
||||||
<div id="root" width="100%" height="100%" align_items="center" justify_content="center">
|
<div id="root" width="100%" height="100%" align_items="center" justify_content="center">
|
||||||
<div flex_direction="row" gap="8" align_items="center" >
|
<div flex_direction="row" gap="8" align_items="center" >
|
||||||
<sprite id="sprite_loading" src_builtin="dashboard/loading.svg" width="32" height="32"/>
|
<sprite id="sprite_loading" src_builtin="dashboard/loading.svg" width="32" height="32" color="on_background"/>
|
||||||
<label translation="LOADING" weight="bold"/>
|
<label translation="LOADING" weight="bold"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<template name="LoadingWithoutText">
|
<template name="LoadingWithoutText">
|
||||||
<div id="root" width="100%" height="100%" align_items="center" justify_content="center">
|
<div id="root" width="100%" height="100%" align_items="center" justify_content="center">
|
||||||
<sprite id="sprite_loading" src_builtin="dashboard/loading.svg" width="32" height="32"/>
|
<sprite id="sprite_loading" src_builtin="dashboard/loading.svg" width="32" height="32" color="on_background"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="theme.xml" />
|
<macro name="home_button" round="8" hover_color="primary" hover_border_color="on_primary" />
|
||||||
|
|
||||||
<macro name="home_button" round="8" color="#00000033" border_color="#FFFFFF77" hover_color="~color_accent" hover_border_color="#FFFFFF" />
|
|
||||||
|
|
||||||
<template name="MenuButton">
|
<template name="MenuButton">
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<layout>
|
<layout>
|
||||||
<template name="Separator">
|
<template name="Separator">
|
||||||
<rectangle width="100%" height="1" color="#FFFFFF77" />
|
<rectangle width="100%" min_height="2" color="outline" />
|
||||||
</template>
|
</template>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="../theme.xml" />
|
<include src="../t_group_box.xml" />
|
||||||
|
|
||||||
|
<!-- tooltip, src, src_ext, name -->
|
||||||
<template name="AppEntry">
|
<template name="AppEntry">
|
||||||
<Button
|
<Button
|
||||||
id="button" width="116" max_width="140" min_height="100" flex_grow="1"
|
id="button" tooltip_side="bottom" tooltip="${tooltip}" width="116" max_width="140" min_height="100" flex_grow="1"
|
||||||
flex_direction="column" overflow="visible" align_items="center" justify_content="center" gap="4"
|
flex_direction="column" overflow="visible" align_items="center" justify_content="center" gap="4"
|
||||||
color="#3385FF10"
|
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<sprite src="${src}" src_ext="${src_ext}" width="64" height="64" />
|
<sprite src="${src}" src_ext="${src_ext}" width="64" height="64" color="#FFFFFF" parent_color="ignore" />
|
||||||
</div>
|
</div>
|
||||||
<div align_items="center" justify_content="center">
|
<div align_items="center" justify_content="center">
|
||||||
<label width="116" weight="bold" text="${name}" size="12" wrap="1" align="center" padding_left="16" padding_right="16" />
|
<label width="116" weight="bold" text="${name}" size="12" wrap="1" align="center" padding_left="16" padding_right="16" />
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="CategoryText">
|
<template name="CategoryText">
|
||||||
<rectangle width="100%" flex_direction="column" round="8" border="2" gradient="vertical" color2="#4477FF09" color="#5588FF10" border_color="#FFFFFF00">
|
<rectangle width="100%" flex_direction="column" round="8" border="2" gradient="vertical" color2="background" color="background_variant" border_color="outline">
|
||||||
<label margin="8" text="${text}" weight="bold" size="22" />
|
<label margin="8" text="${text}" weight="bold" size="22" />
|
||||||
<rectangle height="2" color="~color_accent" margin_left="4" margin_right="4" />
|
<rectangle height="2" color="primary" margin_left="4" margin_right="4" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -39,6 +39,15 @@
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
|
<rectangle macro="group_box">
|
||||||
|
<div align_items="center" gap="8">
|
||||||
|
<sprite src_builtin="dashboard/heart_plus.svg" color="primary" min_width="24" min_height="24"/>
|
||||||
|
<label translation="PINNED_APPS"/>
|
||||||
|
</div>
|
||||||
|
<div id="pinned_apps_parent" flex_direction="row" flex_wrap="wrap" gap="4">
|
||||||
|
<!-- filled-in at runtime -->
|
||||||
|
</div>
|
||||||
|
</rectangle>
|
||||||
<div
|
<div
|
||||||
id="app_list_parent"
|
id="app_list_parent"
|
||||||
flex_direction="row"
|
flex_direction="row"
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,65 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="../t_group_box.xml" />
|
<include src="../t_separator.xml" />
|
||||||
|
|
||||||
|
<template name="TierCell">
|
||||||
|
<div gap="8" align_items="center">
|
||||||
|
<sprite width="28" height="28" src_builtin="dashboard/medal.svg" color="${color}"/>
|
||||||
|
<label text="${text}" weight="bold" size="18" color="${color}" shadow="shadow"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="SupporterCell">
|
||||||
|
<rectangle padding="8" color="background(transparent)" round="8" border="2" border_color="outline" gap="8" align_items="center" flex_direction="row" >
|
||||||
|
<sprite width="24" height="24" src_builtin="dashboard/person.svg"/>
|
||||||
|
<label text="${username}" weight="bold"/>
|
||||||
|
</rectangle>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- icon, nickname -->
|
<!-- icon, nickname -->
|
||||||
<template name="Avatar">
|
<template name="Avatar">
|
||||||
<div flex_direction="column" gap="12" align_items="center">
|
<div flex_direction="column" gap="12" align_items="center">
|
||||||
<image src_builtin="${icon}" width="72" height="72" round="100%" position="relative">
|
<image src_builtin="${icon}" width="64" height="64" round="100%" position="relative">
|
||||||
<rectangle position="absolute" margin_left="-2" margin_top="-2" width="76" height="76" color="#FFFFFF" round="100%"/>
|
<rectangle position="absolute" margin_left="-2" margin_top="-2" width="68" height="68" color="highlight" round="100%"/>
|
||||||
</image>
|
</image>
|
||||||
<label size="14" text="${nickname}"/>
|
<label size="14" text="${nickname}"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<macro name="half"
|
||||||
|
width="50%" gap="16" flex_direction="column" overflow_y="scroll"
|
||||||
|
align_items="center"/>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div position="absolute" width="100%" height="100%" padding="4">
|
<div flex_direction="row" width="100%" min_height="100%" gap="16">
|
||||||
<!-- <rectangle width="100%" height="100%" color="#000000" round="6"/> -->
|
<div macro="half">
|
||||||
</div>
|
<sprite color="#FFAAAA" src_builtin="dashboard/donate.svg" min_width="48" min_height="48"/>
|
||||||
<div margin="32" flex_direction="column" align_items="center" justify_content="center" gap="16" height="100%">
|
<div gap="16" align_items="center" width="100%">
|
||||||
<div gap="16" align_items="center" width="100%">
|
<label align="justified" wrap="1" size="15" translation="DONATE.DESCRIPTION" color="on_background"/>
|
||||||
<sprite color="#FFAAAA" src_builtin="dashboard/donate.svg" min_width="64" min_height="64"/>
|
</div>
|
||||||
<label wrap="1" size="20" translation="DONATE.DESCRIPTION"/>
|
|
||||||
|
<div flex_direction="column" gap="8" align_items="center">
|
||||||
|
<Button id="btn_donate" tooltip="DONATE.BUTTON_TOOLTIP" align_self="baseline">
|
||||||
|
<image src_builtin="dashboard/opencollective_logo.svg" width="200" height="32" margin="8" margin_left="16" margin_right="16"/>
|
||||||
|
</Button>
|
||||||
|
<label text="opencollective.com/wayvr-org"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label weight="bold" size="20" translation="DONATE.THANK_YOU_WAYVR" color="on_background"/>
|
||||||
|
|
||||||
|
<div gap="32">
|
||||||
|
<Avatar icon="dashboard/avatars/galister.png" nickname="galister"/>
|
||||||
|
<Avatar icon="dashboard/avatars/oo8dev.png" nickname="oo8dev"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- vertical separator -->
|
||||||
<div flex_direction="column" gap="8" align_items="center" margin_top="16">
|
<rectangle height="100%" min_width="2" color="outline"/>
|
||||||
<Button id="btn_donate" tooltip="DONATE.BUTTON_TOOLTIP" align_self="baseline">
|
<div macro="half">
|
||||||
<image src_builtin="dashboard/opencollective_logo.svg" width="252" height="42" margin="8" margin_left="16" margin_right="16"/>
|
<div gap="8" align_items="center">
|
||||||
</Button>
|
<label translation="DONATE.CURRENT_SUPPORTERS" size="18" weight="bold" />
|
||||||
<label text="opencollective.com/wayvr-org" color="~color-accent"/>
|
<Button round="100%" text="?" tooltip_str="In last 30 days; the list is updated each day" width="24" height="24"/>
|
||||||
|
</div>
|
||||||
|
<div id="current_supporters" flex_direction="column" gap="8" width="100%"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label weight="bold" size="24" translation="DONATE.THANK_YOU_WAYVR"/>
|
|
||||||
|
|
||||||
<div gap="32" margin_top="16">
|
|
||||||
<Avatar icon="dashboard/avatars/galister.png" nickname="galister"/>
|
|
||||||
<Avatar icon="dashboard/avatars/oo8dev.png" nickname="oo8dev"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<rectangle color="#FFFFFF33" width="100%" height="2"/>
|
|
||||||
|
|
||||||
<rectangle macro="group_box" align_self="start" width="100%">
|
|
||||||
<label weight="bold" size="18" translation="DONATE.CURRENT_SUPPORTERS"/>
|
|
||||||
</rectangle>
|
|
||||||
-->
|
|
||||||
</div>
|
</div>
|
||||||
</elements>
|
</elements>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,25 @@
|
||||||
justify_content="center"
|
justify_content="center"
|
||||||
align_items="center"
|
align_items="center"
|
||||||
flex_grow="1"
|
flex_grow="1"
|
||||||
gap="24">
|
gap="8"
|
||||||
|
>
|
||||||
<image src_builtin="dashboard/splash.png" width="300" height="89" />
|
<image src_builtin="dashboard/splash.png" width="300" height="89" />
|
||||||
<label id="label_hello" size="32" weight="bold" />
|
|
||||||
|
<!-- supporters -->
|
||||||
|
<Button
|
||||||
|
id="btn_supporter"
|
||||||
|
width="fit_content"
|
||||||
|
height="24"
|
||||||
|
text=" "
|
||||||
|
border_color="tertiary(transparent)"
|
||||||
|
hover_border_color="tertiary"
|
||||||
|
color="background_variant(transparent)"
|
||||||
|
hover_color="tertiary(transparent)"/>
|
||||||
|
|
||||||
|
<label id="label_hello" margin_top="24" size="32" weight="bold" color="on_background" />
|
||||||
|
|
||||||
<!-- main button list -->
|
<!-- main button list -->
|
||||||
<div flex_direction="row" gap="8">
|
<div flex_direction="row" gap="8" margin_top="32">
|
||||||
<MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" />
|
<MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" />
|
||||||
<MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" />
|
<MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" />
|
||||||
<MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" />
|
<MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" />
|
||||||
|
|
@ -21,15 +34,15 @@
|
||||||
|
|
||||||
<div gap="8">
|
<div gap="8">
|
||||||
<Button id="btn_welcome_screen" macro="home_button" tooltip="APP_SETTINGS.SHOW_WELCOME_SCREEN">
|
<Button id="btn_welcome_screen" macro="home_button" tooltip="APP_SETTINGS.SHOW_WELCOME_SCREEN">
|
||||||
<sprite src_builtin="dashboard/welcome.svg" width="32" height="32" margin="16"/>
|
<sprite src_builtin="dashboard/welcome.svg" width="32" height="32" margin="16" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button id="btn_website" macro="home_button" tooltip_str="wayvr.org">
|
<Button id="btn_website" macro="home_button" tooltip_str="wayvr.org">
|
||||||
<sprite src_builtin="dashboard/globe.svg" width="32" height="32" margin="16"/>
|
<sprite src_builtin="dashboard/globe.svg" width="32" height="32" margin="16" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button id="btn_donate" macro="home_button" tooltip="DONATE.SUPPORT_US">
|
<Button id="btn_donate" macro="home_button" tooltip="DONATE.SUPPORT_US">
|
||||||
<sprite src_builtin="dashboard/opencollective.svg" width="32" height="32" margin="16"/>
|
<sprite src_builtin="dashboard/opencollective.svg" width="32" height="32" margin="16" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
<elements>
|
<elements>
|
||||||
<div gap="4">
|
<div gap="4">
|
||||||
<Tabs id="tabs">
|
<Tabs id="tabs">
|
||||||
<Tab name="general_settings" translation="GENERAL_SETTINGS" sprite_src_builtin="dashboard/settings.svg" />
|
|
||||||
<Tab name="process_list" translation="PROCESS_LIST" sprite_src_builtin="dashboard/cpu.svg" />
|
<Tab name="process_list" translation="PROCESS_LIST" sprite_src_builtin="dashboard/cpu.svg" />
|
||||||
|
<Tab name="general_settings" translation="GENERAL_SETTINGS" sprite_src_builtin="dashboard/settings.svg" />
|
||||||
<Tab name="debug_timings" translation="DEBUG_INFO" sprite_src_builtin="dashboard/not_a_bug.svg" />
|
<Tab name="debug_timings" translation="DEBUG_INFO" sprite_src_builtin="dashboard/not_a_bug.svg" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div gap="4" id="content" width="100%">
|
<div gap="4" id="content" width="100%">
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="DangerButton">
|
<template name="DangerButton">
|
||||||
<Button id="${id}" color="#AA3333" height="32" tooltip="${translation}_HELP" padding="4" gap="8">
|
<Button id="${id}" color="danger" border_color="danger(rgb-mult-0.5)" height="32" tooltip="${translation}_HELP" padding="4" gap="8">
|
||||||
<sprite src_builtin="${icon}" height="24" width="24" />
|
<sprite src_builtin="${icon}" height="24" width="24" />
|
||||||
<label align="left" translation="${translation}" weight="bold" min_width="200" />
|
<label align="left" translation="${translation}" weight="bold" min_width="200" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -47,7 +47,8 @@
|
||||||
|
|
||||||
<template name="AutostartApp">
|
<template name="AutostartApp">
|
||||||
<div id="${id}_root" flex_direction="row">
|
<div id="${id}_root" flex_direction="row">
|
||||||
<Button id="${id}" color="#AA3333" height="24" padding="4" margin_top="-2" margin_bottom="-2">
|
<Button id="${id}" color="#AA3333" height="24" padding="4" margin_top="-2" margin_bottom="-2"
|
||||||
|
hover_color="danger" hover_border_color="danger(rgb-mult-0.5)" >
|
||||||
<sprite src_builtin="dashboard/close.svg" height="20" width="20" />
|
<sprite src_builtin="dashboard/close.svg" height="20" width="20" />
|
||||||
</Button>
|
</Button>
|
||||||
<div padding_left="8">
|
<div padding_left="8">
|
||||||
|
|
@ -56,17 +57,19 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<macro name="tab_style" color="background" />
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div gap="4">
|
<div gap="4">
|
||||||
<Tabs id="tabs">
|
<Tabs id="tabs">
|
||||||
<Tab name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
<Tab macro="tab_style" name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
||||||
<Tab name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="dashboard/globe.svg" />
|
<Tab macro="tab_style" name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="dashboard/globe.svg" />
|
||||||
<Tab name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
<Tab macro="tab_style" name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
||||||
<Tab name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
<Tab macro="tab_style" name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
||||||
<Tab name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="dashboard/drag.svg" />
|
<Tab macro="tab_style" name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="dashboard/drag.svg" />
|
||||||
<Tab name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
<Tab macro="tab_style" name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
||||||
<Tab name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
<Tab macro="tab_style" name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
||||||
<Tab name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
<Tab macro="tab_style" name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<div flex_wrap="wrap" justify_content="stretch" gap="4" id="settings_root" width="100%">
|
<div flex_wrap="wrap" justify_content="stretch" gap="4" id="settings_root" width="100%">
|
||||||
<!-- filled-in at runtime -->
|
<!-- filled-in at runtime -->
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@
|
||||||
<template name="PageTitle">
|
<template name="PageTitle">
|
||||||
<div position="absolute" align_self="start" justify_self="center" width="100%" margin_top="16" gap="8" align_items="center" justify_content="center">
|
<div position="absolute" align_self="start" justify_self="center" width="100%" margin_top="16" gap="8" align_items="center" justify_content="center">
|
||||||
<sprite width="48" height="48" src_builtin="${icon}" color="#FFFFFF"/>
|
<sprite width="48" height="48" src_builtin="${icon}" color="#FFFFFF"/>
|
||||||
<label size="28" weight="bold" translation="${translation}" shadow="#000000" shadow_x="3" shadow_y="3" />
|
<label size="28" weight="bold" translation="${translation}" color="#FFFFFF" shadow="#000000" shadow_x="3" shadow_y="3" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- text -->
|
<!-- text -->
|
||||||
<template name="TextDesc">
|
<template name="TextDesc">
|
||||||
<label wrap="1" translation="${translation}" size="20" width="500" shadow="#000000" weight="bold"/>
|
<label wrap="1" translation="${translation}" size="20" width="500" color="#FFFFFF" shadow="#000000" weight="bold"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="TextDescBig">
|
<template name="TextDescBig">
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
<label size="20" translation="WELCOME.GUIDE_INTRO"/>
|
<label size="20" translation="WELCOME.GUIDE_INTRO"/>
|
||||||
|
|
||||||
<div gap="4" align_items="center" margin_top="8">
|
<div gap="4" align_items="center" margin_top="8">
|
||||||
<sprite min_width="16" min_height="16" src_builtin="dashboard/info.svg"/>
|
<sprite min_width="16" min_height="16" src_builtin="dashboard/info.svg" color="on_background"/>
|
||||||
<label wrap="1" size="14" translation="WELCOME.REPOSITION_THIS_WINDOW_BY_GRABBING"/>
|
<label wrap="1" size="14" translation="WELCOME.REPOSITION_THIS_WINDOW_BY_GRABBING"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div gap="4" align_items="center">
|
<div gap="4" align_items="center">
|
||||||
<sprite min_width="16" min_height="16" src_builtin="dashboard/info.svg"/>
|
<sprite min_width="16" min_height="16" src_builtin="dashboard/info.svg" color="on_background"/>
|
||||||
<label wrap="1" size="14" translation="WELCOME.LAST_PAGE_INFO"/>
|
<label wrap="1" size="14" translation="WELCOME.LAST_PAGE_INFO"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@
|
||||||
<div macro="video_overlay_content">
|
<div macro="video_overlay_content">
|
||||||
<PageTitle icon="dashboard/click.svg" translation="WELCOME.LASER_COLORS"/>
|
<PageTitle icon="dashboard/click.svg" translation="WELCOME.LASER_COLORS"/>
|
||||||
<div position="relative" flex_direction="row" gap="16" margin="16" align_self="end" justify_self="end" align_items="center">
|
<div position="relative" flex_direction="row" gap="16" margin="16" align_self="end" justify_self="end" align_items="center">
|
||||||
<rectangle flex_direction="column" gap="8" padding="8" round="4" border_color="~color_accent" border="2" >
|
<rectangle flex_direction="column" gap="8" padding="8" round="4" border_color="outline" border="2" >
|
||||||
<label size="12" weight="bold" color="#00FFFF" translation="WELCOME.REGULAR_MODE_BLUE_LASER"/>
|
<label size="12" weight="bold" color="#00FFFF" translation="WELCOME.REGULAR_MODE_BLUE_LASER"/>
|
||||||
<label size="12" weight="bold" color="#FFAA00" translation="WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER"/>
|
<label size="12" weight="bold" color="#FFAA00" translation="WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER"/>
|
||||||
<label size="12" weight="bold" color="#FF88FF" translation="WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER"/>
|
<label size="12" weight="bold" color="#FF88FF" translation="WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER"/>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
<label wrap="1" size="18" width="450" weight="bold" shadow="#000000" translation="WELCOME.LASER_FUNCTIONALITY"/>
|
<label wrap="1" size="18" width="450" weight="bold" color="#ffffff" shadow="#000000" translation="WELCOME.LASER_FUNCTIONALITY"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Video>
|
</Video>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<label shadow="#000000" size="14" weight="bold" wrap="1" color="#aaffcc" translation="WELCOME.GRAB_ONE_HAND"/>
|
<label shadow="#000000" size="14" weight="bold" wrap="1" color="#aaffcc" translation="WELCOME.GRAB_ONE_HAND"/>
|
||||||
<label shadow="#000000" size="14" weight="bold" wrap="1" color="#ccaaff" translation="WELCOME.GRAB_BOTH_HANDS"/>
|
<label shadow="#000000" size="14" weight="bold" wrap="1" color="#ccaaff" translation="WELCOME.GRAB_BOTH_HANDS"/>
|
||||||
<div align_items="center" gap="8">
|
<div align_items="center" gap="8">
|
||||||
<sprite src_builtin="dashboard/info.svg" width="24" height="24" color="#ffff00"/>
|
<sprite src_builtin="dashboard/info.svg" min_width="48" min_height="48" max_width="48" max_height="48" color="#ffff00"/>
|
||||||
<label shadow="#000000" size="16" weight="bold" wrap="1" color="#ffff00" translation="WELCOME.CENTER_MARKER"/>
|
<label shadow="#000000" size="16" weight="bold" wrap="1" color="#ffff00" translation="WELCOME.CENTER_MARKER"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,22 @@
|
||||||
<div flex_direction="row" align_items="center">
|
<div flex_direction="row" align_items="center">
|
||||||
<image src_builtin="dashboard/check_3d.png" width="256" height="256"/>
|
<image src_builtin="dashboard/check_3d.png" width="256" height="256"/>
|
||||||
<div flex_direction="column" gap="16" max_width="480">
|
<div flex_direction="column" gap="16" max_width="480">
|
||||||
<TextDescBig translation="WELCOME.ALL_SET" color="#AAFFAA"/>
|
<TextDescBig translation="WELCOME.ALL_SET" color="tertiary"/>
|
||||||
|
|
||||||
<rectangle color="#AAFFAA33" width="100%" min_height="2"/>
|
<rectangle color="#AAFFAA33" width="100%" min_height="2"/>
|
||||||
|
|
||||||
<label size="16" wrap="1" translation="WELCOME.BASICS"/>
|
<label size="16" wrap="1" translation="WELCOME.BASICS"/>
|
||||||
<label size="16" wrap="1" translation="WELCOME.FEATURES_DOCUMENTATION"/>
|
<label size="16" wrap="1" translation="WELCOME.FEATURES_DOCUMENTATION"/>
|
||||||
<Button id="btn_wayvr_org" align_self="baseline" min_height="32">
|
<Button id="btn_wayvr_org" align_self="baseline" min_height="32">
|
||||||
<sprite src_builtin="dashboard/globe.svg" width="24" height="24" color="~color_accent" margin="8"/>
|
<sprite src_builtin="dashboard/globe.svg" width="24" height="24" margin="8"/>
|
||||||
<label size="18" weight="bold" text="wayvr.org" margin_right="8" />
|
<label size="18" weight="bold" text="wayvr.org" margin_right="8" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<rectangle color="#FFFFFF33" width="100%" min_height="2"/>
|
<rectangle color="#FFFFFF33" width="100%" min_height="2"/>
|
||||||
|
|
||||||
<Button id="btn_home_screen" min_height="48">
|
<Button id="btn_home_screen" min_height="48" >
|
||||||
<sprite src_builtin="dashboard/check.svg" width="32" height="32" color="~color_accent" margin="8"/>
|
<sprite src_builtin="dashboard/check.svg" width="32" height="32" margin="8"/>
|
||||||
<label size="20" weight="bold" translation="WELCOME.FINISH_TUTORIAL" margin_right="8" />
|
<label color="on_background" size="20" weight="bold" translation="WELCOME.FINISH_TUTORIAL" margin_right="8" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<layout>
|
|
||||||
<theme>
|
|
||||||
<var key="color_menu_dark" value="#0A0A0ACC" />
|
|
||||||
<var key="color_accent" value="#008cff" />
|
|
||||||
<var key="color_top_panel" value="#00000099" />
|
|
||||||
<var key="color_bottom_panel" value="#141e28" />
|
|
||||||
</theme>
|
|
||||||
</layout>
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<layout>
|
<layout>
|
||||||
<template name="Subtext">
|
<template name="Subtext">
|
||||||
<div flex_direction="row" gap="8">
|
<div flex_direction="row" gap="8" max_width="100%">
|
||||||
<label weight="bold" text="${title}" />
|
<label weight="bold" text="${title}" wrap="1" />
|
||||||
<label id="${label_id}" />
|
<label id="${label_id}" wrap="1" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -15,12 +15,10 @@
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div flex_direction="row" gap="16" flex_grow="1">
|
<div flex_direction="row" gap="16" flex_grow="1">
|
||||||
<rectangle macro="group_box" id="icon_parent" padding="16" color="#0033aa66" color2="#00000022" gradient="vertical" justify_content="center">
|
<rectangle macro="group_box" id="icon_parent" padding="16" color="background_variant(opacity-0.5)" color2="background(opacity-0.5)" gradient="vertical" justify_content="center"/>
|
||||||
|
<div flex_direction="column" gap="8" flex_grow="1">
|
||||||
</rectangle>
|
|
||||||
<div flex_direction="column" gap="8" flex_grow="1" max_width="720">
|
|
||||||
<label id="label_title" weight="bold" size="32" overflow="hidden" />
|
<label id="label_title" weight="bold" size="32" overflow="hidden" />
|
||||||
<Subtext label_id="label_exec" overflow="hidden" />
|
<Subtext label_id="label_exec"/>
|
||||||
<Separator />
|
<Separator />
|
||||||
<RadioGroup id="radio_compositor" flex_direction="row" gap="16">
|
<RadioGroup id="radio_compositor" flex_direction="row" gap="16">
|
||||||
<RadioBox translation="APP_LAUNCHER.MODE.NATIVE" value="Native" checked="1" />
|
<RadioBox translation="APP_LAUNCHER.MODE.NATIVE" value="Native" checked="1" />
|
||||||
|
|
@ -30,32 +28,33 @@
|
||||||
<label translation="APP_LAUNCHER.RES_TITLE" />
|
<label translation="APP_LAUNCHER.RES_TITLE" />
|
||||||
<RadioGroup id="radio_res" flex_direction="row" gap="16">
|
<RadioGroup id="radio_res" flex_direction="row" gap="16">
|
||||||
<RadioBox text="1440p" value="Res1440" />
|
<RadioBox text="1440p" value="Res1440" />
|
||||||
<RadioBox text="1080p" value="Res1080" checked="1" />
|
<RadioBox text="1080p" value="Res1080"/>
|
||||||
<RadioBox text="720p" value="Res720" />
|
<RadioBox text="720p" value="Res720" />
|
||||||
<RadioBox text="480p" value="Res480" />
|
<RadioBox text="480p" value="Res480" />
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
<Separator />
|
<Separator />
|
||||||
<label translation="APP_LAUNCHER.ASPECT_TITLE" />
|
<label translation="APP_LAUNCHER.ASPECT_TITLE" />
|
||||||
<RadioGroup id="radio_orientation" flex_direction="row" gap="16">
|
<RadioGroup id="radio_orientation" flex_direction="row" gap="16">
|
||||||
<RadioBox translation="APP_LAUNCHER.ASPECT.WIDE" value="Wide" tooltip_str="16:9" checked="1" />
|
<RadioBox translation="APP_LAUNCHER.ASPECT.WIDE" value="Wide" tooltip_str="16:9"/>
|
||||||
<RadioBox translation="APP_LAUNCHER.ASPECT.SEMI_WIDE" value="SemiWide" tooltip_str="3:2" />
|
<RadioBox translation="APP_LAUNCHER.ASPECT.SEMI_WIDE" value="SemiWide" tooltip_str="3:2" />
|
||||||
<RadioBox translation="APP_LAUNCHER.ASPECT.SQUARE" value="Square" tooltip_str="1:1" />
|
<RadioBox translation="APP_LAUNCHER.ASPECT.SQUARE" value="Square" tooltip_str="1:1" />
|
||||||
<RadioBox translation="APP_LAUNCHER.ASPECT.SEMI_TALL" value="SemiTall" tooltip_str="2:3" />
|
<RadioBox translation="APP_LAUNCHER.ASPECT.SEMI_TALL" value="SemiTall" tooltip_str="2:3" />
|
||||||
<RadioBox translation="APP_LAUNCHER.ASPECT.TALL" value="Tall" tooltip_str="9:16" />
|
<RadioBox translation="APP_LAUNCHER.ASPECT.TALL" value="Tall" tooltip_str="9:16" />
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
<!-- Separator /> // saved settings override this, so let's hide it for now
|
|
||||||
<label translation="APP_LAUNCHER.POS_TITLE" />
|
|
||||||
<RadioGroup id="radio_pos" flex_direction="row" gap="16">
|
|
||||||
<RadioBox translation="APP_LAUNCHER.POS.FLOATING" value="Floating" tooltip_str="APP_LAUNCHER.POS.FLOATING_HELP" />
|
|
||||||
<RadioBox translation="APP_LAUNCHER.POS.ANCHORED" value="Anchored" tooltip_str="APP_LAUNCHER.POS.ANCHORED_HELP" checked="1" />
|
|
||||||
<RadioBox translation="APP_LAUNCHER.POS.STATIC" value="Static" tooltip_str="APP_LAUNCHER.POS.STATIC_HELP" />
|
|
||||||
</RadioGroup -->
|
|
||||||
<Separator />
|
<Separator />
|
||||||
<div flex_direction="row" justify_content="space_between" gap="16">
|
<CheckBox id="cb_autostart" translation="APP_LAUNCHER.AUTOSTART" align_self="baseline"/>
|
||||||
<CheckBox id="cb_autostart" translation="APP_LAUNCHER.AUTOSTART" />
|
<div flex_direction="row" align_items="end" justify_content="center" gap="8" margin_top="8">
|
||||||
<Button id="btn_launch" align_self="baseline" color="#44ce22FF" padding_top="4" padding_bottom="4" round="8" padding_right="12" min_height="40">
|
<Button id="btn_unpin" color="danger" padding_left="8" padding_right="8" round="8" min_height="40">
|
||||||
|
<sprite src_builtin="dashboard/heart_minus.svg" width="32" height="32" />
|
||||||
|
<label translation="REMOVE_FROM_FAVOURITES" weight="bold" size="17" />
|
||||||
|
</Button>
|
||||||
|
<Button id="btn_pin" color="secondary" padding_left="8" padding_right="8" round="8" min_height="40" tooltip="ADD_TO_FAVOURITES_HINT">
|
||||||
|
<sprite src_builtin="dashboard/heart_plus.svg" width="32" height="32" />
|
||||||
|
<label translation="ADD_TO_FAVOURITES" weight="bold" size="17" />
|
||||||
|
</Button>
|
||||||
|
<Button id="btn_launch" color="primary" padding_left="8" padding_right="8" round="8" min_width="200" min_height="40">
|
||||||
<sprite src_builtin="dashboard/play.svg" width="32" height="32" />
|
<sprite src_builtin="dashboard/play.svg" width="32" height="32" />
|
||||||
<label translation="APP_LAUNCHER.LAUNCH" weight="bold" size="17" shadow="#00000099" />
|
<label translation="APP_LAUNCHER.LAUNCH" weight="bold" size="17" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
<template name="DeviceSlider">
|
<template name="DeviceSlider">
|
||||||
<rectangle macro="group_box">
|
<rectangle macro="group_box">
|
||||||
<div width="100%" align_items="center" justify_content="center" gap="8">
|
<div width="100%" align_items="center" justify_content="center" gap="8">
|
||||||
<sprite src_builtin="${device_icon}" width="16" height="16" />
|
<sprite src_builtin="${device_icon}" width="16" height="16" color="on_background" />
|
||||||
<label text="${device_name}" margin_right="8" size="12" weight="bold" />
|
<label text="${device_name}" margin_right="8" size="12" weight="bold" color="on_background" />
|
||||||
</div>
|
</div>
|
||||||
<div width="100%" align_items="center">
|
<div width="100%" align_items="center">
|
||||||
<CheckBox id="checkbox" />
|
<CheckBox id="checkbox" />
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<template name="Card">
|
<template name="Card">
|
||||||
<rectangle macro="group_box">
|
<rectangle macro="group_box">
|
||||||
<div width="100%" align_items="center" justify_content="center">
|
<div width="100%" align_items="center" justify_content="center">
|
||||||
<label text="${card_name}" size="12" weight="bold" />
|
<label text="${card_name}" size="12" weight="bold" color="on_background" />
|
||||||
</div>
|
</div>
|
||||||
<Button id="btn_card" text="${profile_name}" width="100%" height="32" />
|
<Button id="btn_card" text="${profile_name}" width="100%" height="32" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<template name="SelectAudioProfileText">
|
<template name="SelectAudioProfileText">
|
||||||
<div align_items="center" gap="8">
|
<div align_items="center" gap="8">
|
||||||
<Button width="48" height="32" id="btn_back">
|
<Button width="48" height="32" id="btn_back">
|
||||||
<sprite src_builtin="dashboard/back.svg" width="24" height="24" />
|
<sprite src_builtin="dashboard/back.svg" width="24" height="24" color="on_background" />
|
||||||
</Button>
|
</Button>
|
||||||
<label translation="AUDIO.SELECT_AUDIO_CARD_PROFILE" size="14" weight="bold" />
|
<label translation="AUDIO.SELECT_AUDIO_CARD_PROFILE" size="14" weight="bold" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -58,7 +58,8 @@
|
||||||
sprite_src_builtin="dashboard/magic_wand.svg"
|
sprite_src_builtin="dashboard/magic_wand.svg"
|
||||||
min_width="32"
|
min_width="32"
|
||||||
tooltip="AUDIO.AUTO_SWITCH_TO_VR_AUDIO"
|
tooltip="AUDIO.AUTO_SWITCH_TO_VR_AUDIO"
|
||||||
color="~color_accent"
|
color="primary"
|
||||||
|
sprite_color="on_primary"
|
||||||
tooltip_side="right" />
|
tooltip_side="right" />
|
||||||
|
|
||||||
<BottomButton id="btn_sinks" src_builtin="dashboard/volume.svg" translation="AUDIO.SPEAKERS" />
|
<BottomButton id="btn_sinks" src_builtin="dashboard/volume.svg" translation="AUDIO.SPEAKERS" />
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
<rectangle macro="group_box" id="${id}">
|
<rectangle macro="group_box" id="${id}">
|
||||||
<!-- top row -->
|
<!-- top row -->
|
||||||
<div flex_direction="row" gap="8" align_items="center">
|
<div flex_direction="row" gap="8" align_items="center">
|
||||||
<sprite src_builtin="dashboard/controller.svg" width="24" height="24"/>
|
<sprite src_builtin="dashboard/controller.svg" width="24" height="24" color="on_background"/>
|
||||||
<label translation="${translation}" color="~color_accent" weight="bold" size="14" />
|
<label translation="${translation}" color="primary" weight="bold" size="14" />
|
||||||
</div>
|
</div>
|
||||||
<!-- filled-in at runtime -->
|
<!-- filled-in at runtime -->
|
||||||
</rectangle>
|
</rectangle>
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<div flex_direction="column" gap="8" align_items="center" overflow_y="scroll" width="100%" padding="16">
|
<div flex_direction="column" gap="8" align_items="center" overflow_y="scroll" width="100%" padding="16">
|
||||||
<div id="list_parent" flex_direction="column" gap="6" width="100%"></div>
|
<div id="list_parent" flex_direction="column" gap="6" width="100%"></div>
|
||||||
</div>
|
</div>
|
||||||
<rectangle color="#000000cc" flex_direction="row" gap="8" justify_content="end" padding="8">
|
<rectangle color="background_contrast" flex_direction="row" gap="8" justify_content="end" padding="8">
|
||||||
<Button id="btn_cancel" sprite_src_builtin="dashboard/cancel.svg" min_width="100" height="32" translation="APP_SETTINGS.CANCEL" />
|
<Button id="btn_cancel" sprite_src_builtin="dashboard/cancel.svg" min_width="100" height="32" translation="APP_SETTINGS.CANCEL" />
|
||||||
<Button id="btn_save" sprite_src_builtin="dashboard/check.svg" min_width="100" height="32" translation="APP_SETTINGS.SAVE" />
|
<Button id="btn_save" sprite_src_builtin="dashboard/check.svg" min_width="100" height="32" translation="APP_SETTINGS.SAVE" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<layout>
|
||||||
|
<template name="ColorPaletteButton">
|
||||||
|
<Button id="${id}" width="350" flex_direction="column" justify_content="space_around" tooltip="${tooltip}" tooltip_side="bottom"
|
||||||
|
color="${background}" hover_color="${background_variant}" border_color="${outline}" hover_border_color="${highlight}" padding="16" margin="4" >
|
||||||
|
<label text="${text}" size="24" weight="bold" color="${on_background}" parent_color="ignore"/>
|
||||||
|
<div flex_direction="row" width="100%" justify_content="space_evenly" padding_top="16" >
|
||||||
|
<rectangle round="100%" width="32" height="32" color="${primary}" border="2" border_color="${on_primary}" />
|
||||||
|
<rectangle round="100%" width="32" height="32" color="${secondary}" border="2" border_color="${on_secondary}" />
|
||||||
|
<rectangle round="100%" width="32" height="32" color="${tertiary}" border="2" border_color="${on_tertiary}" />
|
||||||
|
<rectangle round="100%" width="32" height="32" color="${danger}" border="2" border_color="${on_danger}" />
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="CustomPaletteButton">
|
||||||
|
<Button id="custom_btn" width="350" flex_direction="column" justify_content="space_around" padding="16" margin="4" >
|
||||||
|
<label translation="APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL" size="16" weight="bold" />
|
||||||
|
<label translation="APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL2" size="14" color="on_background_variant" />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<elements>
|
||||||
|
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
||||||
|
<div id="list_parent" flex_grow="1" flex_wrap="wrap" flex_direction="row" gap="4" width="100%" justify_content="center"></div>
|
||||||
|
</div>
|
||||||
|
</elements>
|
||||||
|
</layout>
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<div id="content" flex_direction="column" gap="8" width="100%">
|
<div id="content" flex_direction="column" gap="8" width="100%">
|
||||||
<label translation="DOWNLOADING_FILE" size="24" weight="bold"/>
|
<label translation="DOWNLOADING_FILE" size="24" weight="bold"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<label id="label_target_path" color="~color_text_translucent" />
|
<label id="label_target_path" color="on_background" />
|
||||||
|
|
||||||
<div gap="8" align_items="center">
|
<div gap="8" align_items="center">
|
||||||
<div id="loading_parent"/>
|
<div id="loading_parent"/>
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
<label weight="bold" id="label_author" text="Unknown" />
|
<label weight="bold" id="label_author" text="Unknown" />
|
||||||
</div>
|
</div>
|
||||||
<label id="label_description" wrap="1" text="No description available" />
|
<label id="label_description" wrap="1" text="No description available" />
|
||||||
<Button id="btn_launch" align_self="baseline" color="#44ce22FF" padding_top="4" padding_bottom="4" round="8" padding_right="12" min_width="200" min_height="40">
|
<Button id="btn_launch" align_self="baseline" color="primary" border_color="primary(rgb-mult-0.5)" padding_top="4" padding_bottom="4" round="8" padding_right="12" min_width="200" min_height="40">
|
||||||
<sprite src_builtin="dashboard/play.svg" width="32" height="32" />
|
<sprite src_builtin="dashboard/play.svg" width="32" height="32" />
|
||||||
<label text="Launch" weight="bold" size="17" shadow="#00000099" />
|
<label text="Launch" weight="bold" size="17" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- id, text -->
|
<!-- id, text -->
|
||||||
<template name="InputProfileButton">
|
<template name="InputProfileButton">
|
||||||
<Button id="${id}" width="350" gap="8" justify_content="start" >
|
<Button id="${id}" width="350" gap="8" justify_content="start" >
|
||||||
<sprite margin_left="8" src_builtin="dashboard/controller.svg" min_width="24" min_height="24"/>
|
<sprite margin_left="8" src_builtin="dashboard/controller.svg" min_width="24" min_height="24" />
|
||||||
<label text="${text}" weight="bold"/>
|
<label text="${text}" weight="bold"/>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="../theme.xml" />
|
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div
|
<div
|
||||||
consume_mouse_events="1"
|
consume_mouse_events="1"
|
||||||
|
|
@ -11,33 +9,33 @@
|
||||||
flex_direction="column"
|
flex_direction="column"
|
||||||
position="absolute"
|
position="absolute"
|
||||||
>
|
>
|
||||||
<!-- Top black bar -->
|
<!-- Top bar -->
|
||||||
<rectangle
|
<rectangle
|
||||||
position="relative"
|
position="relative"
|
||||||
color="#000000"
|
color="background_contrast"
|
||||||
width="100%" height="48"
|
width="100%" height="48"
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- Shine effect at the top -->
|
<!-- Shine effect at the top -->
|
||||||
<rectangle position="absolute" width="100%" height="2" round="4" color="#ffffff22" />
|
<rectangle position="absolute" width="100%" height="3" round="4" color="highlight(opacity-0.1)" />
|
||||||
|
|
||||||
<!-- Top bar contents -->
|
<!-- Top bar contents -->
|
||||||
<div gap="16" align_items="center">
|
<div gap="16" align_items="center">
|
||||||
<!-- Back button -->
|
<!-- Back button -->
|
||||||
<Button id="but_back" width="48" height="48" color="#ffffff00" border_color="#ffffff00">
|
<Button id="but_back" width="48" height="48" color="on_background_contrast(transparent)" border_color="on_background_contrast(transparent)">
|
||||||
<sprite src_builtin="dashboard/back.svg" width="24" height="24" />
|
<sprite src_builtin="dashboard/back.svg" width="24" height="24" color="on_background_contrast" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<label id="popup_title" weight="bold" size="18" />
|
<label id="popup_title" color="on_background_contrast" weight="bold" size="18" />
|
||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
|
|
||||||
<rectangle
|
<rectangle
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
color="#010310fe"
|
color="background_contrast(opacity-0.98)"
|
||||||
color2="#051c55fc"
|
color2="background(opacity-0.99)"
|
||||||
gradient="vertical"
|
gradient="vertical"
|
||||||
position="relative"
|
position="relative"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<div id="resolution_buttons" gap="8" flex_direction="row">
|
<div id="resolution_buttons" gap="8" flex_direction="row">
|
||||||
<!-- filled-in at runtime -->
|
<!-- filled-in at runtime -->
|
||||||
</div>
|
</div>
|
||||||
<image id="image" width="400" height="200" round="8" border="2" border_color="~color_accent"/>
|
<image id="image" width="400" height="200" round="8" border="2" border_color="primary"/>
|
||||||
<label id="label_author" weight="bold"/>
|
<label id="label_author" weight="bold"/>
|
||||||
<label id="label_description" wrap="1"/>
|
<label id="label_description" wrap="1"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
-->
|
-->
|
||||||
<template name="ResolutionPip">
|
<template name="ResolutionPip">
|
||||||
<rectangle color="${color}" padding_left="4" padding_right="4" padding_top="2" padding_bottom="2" round="3" align_self="start">
|
<rectangle color="${color}" padding_left="4" padding_right="4" padding_top="2" padding_bottom="2" round="3" align_self="start">
|
||||||
<label text="${text}" weight="bold" size="12" shadow="#000000" shadow_x="2" shadow_y="2"/>
|
<label text="${text}" weight="bold" size="12" color="#FFFFFF" shadow="#000000" shadow_x="2" shadow_y="2"/>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</template>
|
</template>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
||||||
|
|
@ -1,114 +1,56 @@
|
||||||
{
|
{
|
||||||
"HOME_SCREEN": "Startbildschirm",
|
"DEFINITIONS": {
|
||||||
"MONADO_RUNTIME": "Monado-Laufzeitumgebung",
|
"ANCHORED": "Verankert",
|
||||||
"APPLICATIONS": "Anwendungen",
|
"FLOATING": "Schwebend",
|
||||||
"GAMES": "Spiele",
|
"STATIC": "Statisch",
|
||||||
"SETTINGS": "Einstellungen",
|
"SET": "Set",
|
||||||
"HELLO_USER": "Hallo, {USER}!",
|
"WATCH": "Handgelenk-Uhr",
|
||||||
"GENERAL_SETTINGS": "Allgemeine Einstellungen",
|
"DASHBOARD": "Dashboard",
|
||||||
"APPLICATION_LAUNCHER": "Anwendung Launcher",
|
"EDIT_MODE": "Bearbeitungsmodus",
|
||||||
"APP_SETTINGS": {
|
"SETTINGS": "Einstellungen",
|
||||||
"HIDE_USERNAME": "Benutzernamen ausblenden",
|
"KEYBOARD": "Tastatur",
|
||||||
"OPAQUE_BACKGROUND": "Undurchsichtiger Hintergrund",
|
"TASKBAR": "Taskleiste",
|
||||||
"LOOK_AND_FEEL": "Aussehen und Verhalten",
|
"FEATURES": "Features",
|
||||||
"HIDE_GRAB_HELP": "Greif-Hilfe ausblenden",
|
"OVERLAY": "Overlay",
|
||||||
"ANIMATION_SPEED": "UI-Animationsgeschwindigkeit",
|
"SKYMAP": "Skymap",
|
||||||
"ROUND_MULTIPLIER": "UI-Kantenrundung",
|
"PLAYSPACE": "Playspace",
|
||||||
"USE_SKYBOX": "Skybox aktivieren",
|
"D_PAD": "Steuerkreuz"
|
||||||
"USE_PASSTHROUGH": "Passthrough aktivieren",
|
},
|
||||||
"CLOCK_12H": "12-Stunden-Uhr",
|
"ACTIONS": {
|
||||||
"FEATURES": "Funktionen",
|
"RECENTER_PLAYSPACE": "Playspace neu zentrieren"
|
||||||
"NOTIFICATIONS_ENABLED": "Benachrichtigungen aktivieren",
|
},
|
||||||
"NOTIFICATIONS_SOUND_ENABLED": "Benachrichtigungstöne",
|
"APP_LAUNCHER": {
|
||||||
"KEYBOARD_SOUND_ENABLED": "Tastengeräusche",
|
"ASPECT": {
|
||||||
"SPACE_DRAG_MULTIPLIER": "Raum-Drag-Multiplikator",
|
"SEMI_TALL": "Halbhoch",
|
||||||
"SPACE_DRAG_UNLOCKED": "Erlaube Space-Drag auf allen Achsen",
|
"SEMI_WIDE": "Halbweit",
|
||||||
"SPACE_ROTATE_UNLOCKED": "Erlaube Drehungen in allen Achsen",
|
"SQUARE": "Quadratisch",
|
||||||
"BLOCK_GAME_INPUT": "Spieleingabe blockieren",
|
"TALL": "Hochkant",
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignoriere Watch beim Blockieren der Eingabe",
|
"WIDE": "Breitbild"
|
||||||
"CONTROLS": "Steuerung",
|
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "Mausbewegung bei Triggerberührung",
|
|
||||||
"LEFT_HANDED_MOUSE": "Linkshändige Maus",
|
|
||||||
"ALLOW_SLIDING": "Stabinteraktion während des Greifens",
|
|
||||||
"INVERT_SCROLL_DIRECTION_X": "Horizontale Scrollrichtung umkehren",
|
|
||||||
"INVERT_SCROLL_DIRECTION_Y": "Vertikale Bildlaufrichtung umkehren",
|
|
||||||
"SCROLL_SPEED": "Scrollgeschwindigkeit",
|
|
||||||
"LONG_PRESS_DURATION": "Dauer für lange Drückvorgänge",
|
|
||||||
"POINTER_LERP_FACTOR": "Zeigerglättung",
|
|
||||||
"CLICK_FREEZE_TIME_MS": "Klick-Freeze-Zeit (ms)",
|
|
||||||
"MISC": "Verschiedenes",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "Standardmäßig Apps im Kompatibilitätsmodus ausführen",
|
|
||||||
"UPRIGHT_SCREEN_FIX": "Bildschirm-Drehkorrektur",
|
|
||||||
"DOUBLE_CURSOR_FIX": "Doppelter Cursor Fix",
|
|
||||||
"SCREEN_RENDER_DOWN": "Bildschirm bei niedrigerer Auflösung rendern",
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Behebt hochstehende Bildschirme auf einigen Desktops",
|
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Aktivieren Sie dies, wenn Sie 2 Cursor sehen",
|
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Hilft bei der Präzision von Doppelklicks",
|
|
||||||
"LEFT_HANDED_MOUSE_HELP": "Verwenden Sie diese Option, wenn die Maustasten vertauscht sind",
|
|
||||||
"BLOCK_GAME_INPUT_HELP": "Blockiert alle Eingaben, wenn ein Overlay angefahren wird",
|
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Blockiere die Eingabe nicht, wenn die Überwachung aktiviert ist",
|
|
||||||
"USE_SKYBOX_HELP": "Zeige einen Skybox, wenn keine Szenen-App oder Passthrough vorhanden ist",
|
|
||||||
"USE_PASSTHROUGH_HELP": "Aktiviere Passthrough, falls die XR-Laufzeitumgebung dies unterstützt",
|
|
||||||
"SCREEN_RENDER_DOWN_HELP": "Hilft bei Aliasing auf hochauflösenden Bildschirmen",
|
|
||||||
"SETS_ON_WATCH": "Sets auf der Watch",
|
|
||||||
"TROUBLESHOOTING": "Fehlerbehebung",
|
|
||||||
"CLEAR_SAVED_STATE": "Gespeicherten Zustand löschen",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "PipeWire Tokens löschen",
|
|
||||||
"DELETE_ALL_CONFIGS": "Konfiguration löschen",
|
|
||||||
"RESTART_SOFTWARE": "Software neu starten",
|
|
||||||
"CLEAR_SAVED_STATE_HELP": "Sets und Overlay-Positionen zurücksetzen",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "Bildschirmauswahl beim nächsten Start abfragen",
|
|
||||||
"DELETE_ALL_CONFIGS_HELP": "Entfernen Sie alle Konfigurationsdateien aus conf.d",
|
|
||||||
"RESTART_SOFTWARE_HELP": "Einstellungen anwenden, die einen Neustart erfordern",
|
|
||||||
"CAPTURE_METHOD": "Wayland-Bildschirmaufnahme",
|
|
||||||
"CAPTURE_METHOD_HELP": "Versuchen Sie, dies zu ändern, wenn Sie\nschwarze oder fehlerhafte Bildschirme erleben",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK": "Keyboard-Mittelklick",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK_HELP": "Modifikator bei Eingabe mit violettem Laser",
|
|
||||||
"OPTION": {
|
|
||||||
"AUTO": "Automatisch",
|
|
||||||
"AUTO_HELP": "Bildschirmkopie GPU falls unterstützt,\nansonsten PipeWire GPU.",
|
|
||||||
"PIPEWIRE_HELP": "Schnelle GPU-Erfassung,\nStandard auf allen Desktops.",
|
|
||||||
"PW_FALLBACK_HELP": "Langsame Methode mit hoher CPU-Auslastung.\nVersuchen Sie es, falls PipeWire GPU nicht funktioniert.",
|
|
||||||
"SCREENCOPY_GPU_HELP": "Schnell, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway",
|
|
||||||
"SCREENCOPY_HELP": "Langsam, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway",
|
|
||||||
"NONE": "Keine",
|
|
||||||
"HMD_PINCH": "HMD + Kneifen",
|
|
||||||
"EYE_PINCH": "Auge + Kneifen",
|
|
||||||
"EYE_ONLY": "Nur Auge",
|
|
||||||
"HMD_ONLY": "Nur HMD",
|
|
||||||
"NONE_INPUT_HELP": "Maus und Tastatur nicht emulieren.\nEs wird nicht möglich sein, mit Displays zu interagieren.",
|
|
||||||
"UINPUT": "Gerätesimulation",
|
|
||||||
"UINPUT_HELP": "Verwendet das uinput-Modul, um ein Gerät zu emulieren.\nIhr Benutzer muss in der Gruppe „input“ sein.\nBekannt dafür, auf den meisten Desktops gut zu funktionieren.",
|
|
||||||
"WL_VIRTUAL": "Wayland-virtueller Input",
|
|
||||||
"WL_VIRTUAL_HELP": "Sendet Ereignisse an den Wayland-Compositor unter Verwendung von\nzwlr_virtual_pointer und zwp_virtual_keyboard.\nFunktioniert nur zuverlässig auf einigen Desktops.\nFunktioniert NICHT auf KDE, GNOME oder COSMIC."
|
|
||||||
},
|
},
|
||||||
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen",
|
"ASPECT_TITLE": "Seitenverhältnis",
|
||||||
"HANDSFREE_POINTER": "Freihändige Modus",
|
"AUTOSTART": "Automatisch beim Start ausführen",
|
||||||
"HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt.",
|
"LAUNCH": "Starten",
|
||||||
"UI_GRADIENT_INTENSITY": "UI-Verlaufsintensität",
|
"MODE": {
|
||||||
"RESET_PLAYSPACE": "Spielbereich zurücksetzen",
|
"CAGE": "Kompatibilitätsmodus (Cage)",
|
||||||
"RESET_PLAYSPACE_HELP": "Den Abstand des Spielbereichs zurücksetzen.",
|
"NATIVE": "Nativer Modus"
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION": "Posen beim Interagieren mit der Tastatur blockieren",
|
},
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Verhindert, dass das Spiel Posen empfängt, wenn die Tastatur angefahren wird und „Spieleingabe blockieren“ aktiviert ist",
|
"RES_TITLE": "Auflösung"
|
||||||
"LANGUAGE": "Sprache",
|
},
|
||||||
"REQUIRES_RESTART": "Erfordert Neustart",
|
"APP_SETTINGS": {
|
||||||
"GRID_OPACITY": "Bodenraster-Undurchsichtigkeit",
|
"ALLOW_SLIDING": "Stick-Interaktion beim Greifen",
|
||||||
"GRID_OPACITY_HELP": "Undurchsichtigkeit des Bodenrasters, wenn der Skybox aktiviert ist",
|
"ANIMATION_SPEED": "UI-Animationsgeschwindigkeit",
|
||||||
"BROWSE_ONLINE_CATALOG": "Online-Katalog durchsuchen...",
|
"AUTOSTART_APPS": "Beim Start ausführen",
|
||||||
"BROWSE_SKYMAPS": "Skymaps durchsuchen",
|
"BLOCK_GAME_INPUT": "Game-Input blockieren",
|
||||||
"COLOR_KEYING": "Farbschlüsselung",
|
"BLOCK_GAME_INPUT_HELP": "Blockiert alle Eingaben, wenn ein Overlay fokussiert ist",
|
||||||
"NO_SKYMAPS_FOUND": "Keine Skymaps gefunden",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Uhr beim Blockieren der Eingabe ignorieren",
|
||||||
"SELECT_VARIANT": "Variante auswählen",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Eingabe nicht blockieren, wenn die Handgelenk-Uhr fokussiert ist",
|
||||||
"SHOW_WELCOME_SCREEN": "Begrüßungsbildschirm anzeigen",
|
"BLOCK_POSES_ON_KBD_INTERACTION": "Posen bei Tastaturinteraktion blockieren",
|
||||||
"SKYBOX": "Skybox",
|
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Verhindert die Übertragung von Posen an das Spiel, wenn die Tastatur fokussiert ist und „Spielsteuerung blockieren“ aktiviert ist",
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "Diese Skymap wurde bereits heruntergeladen. Wählen Sie die gewünschte Aktion aus.",
|
|
||||||
"WATCH_VIEW_ANGLE": "Betrachtungswinkel der Watch",
|
|
||||||
"WATCH_VIEW_ANGLE_HELP": "Steuerung, wie die Watch ausgeblendet wird",
|
|
||||||
"BINDINGS": {
|
"BINDINGS": {
|
||||||
"COMP": {
|
"COMP": {
|
||||||
"CLICK": "Klicken",
|
"CLICK": "Klicken",
|
||||||
"FORCE": "Kraft",
|
"FORCE": "Druckkraft",
|
||||||
"TOUCH": "Berührung",
|
"TOUCH": "Berühren",
|
||||||
"VALUE": "Wert",
|
"VALUE": "Wert",
|
||||||
"PROXIMITY": "Nähe",
|
"PROXIMITY": "Nähe",
|
||||||
"X_AXIS": "X-Achse",
|
"X_AXIS": "X-Achse",
|
||||||
|
|
@ -116,185 +58,292 @@
|
||||||
},
|
},
|
||||||
"TYPE": {
|
"TYPE": {
|
||||||
"BUMPER": "Bumper",
|
"BUMPER": "Bumper",
|
||||||
"DPAD_UP": "D-Pad oben",
|
"DPAD_UP": "Steuerkreuz oben",
|
||||||
"DPAD_DOWN": "D-Pad Runter",
|
"DPAD_DOWN": "Steuerkreuz unten",
|
||||||
"DPAD_LEFT": "D-Pad Links",
|
"DPAD_LEFT": "Steuerkreuz links",
|
||||||
"DPAD_RIGHT": "D-Pad Rechts",
|
"DPAD_RIGHT": "Steuerkreuz rechts",
|
||||||
"JOYSTICK": "Joystick",
|
"JOYSTICK": "Joystick",
|
||||||
"MENU": "Menü",
|
"MENU": "Menü",
|
||||||
"SHOULDER": "Schulter",
|
"SHOULDER": "Schulterknopftaste",
|
||||||
"SQUEEZE": "Greifen",
|
"SQUEEZE": "Griff",
|
||||||
"SYSTEM": "System",
|
"SYSTEM": "System",
|
||||||
"THUMBREST": "Daumenuflage",
|
"THUMBREST": "Daumenauflage",
|
||||||
"THUMBSTICK": "Thumbstick",
|
"THUMBSTICK": "Thumbstick",
|
||||||
"TRACKPAD": "Trackpad",
|
"TRACKPAD": "Trackpad",
|
||||||
"TRIGGER": "Trigger",
|
"TRIGGER": "Trigger",
|
||||||
"VIEW": "Ansehen"
|
"VIEW": "View"
|
||||||
},
|
},
|
||||||
"CLICK": {
|
"CLICK": {
|
||||||
"ANY": "Beliebig",
|
"ANY": "Beliebig",
|
||||||
"DOUBLE": "Doppeltippen",
|
"DOUBLE": "Doppeltippen",
|
||||||
"TRIPLE": "Dreifach-Tippen",
|
"TRIPLE": "Dreifachklick",
|
||||||
"TYPE": "Anzahl der Taps"
|
"TYPE": "Anzahl der Klicks"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"CLICK": "Klick*",
|
"CLICK": "Klick*",
|
||||||
"GRAB": "Greifen*",
|
"GRAB": "Greifen*",
|
||||||
"ALT_CLICK": "Benutzerdefiniertes Shell-Exec (alt_click in Konfiguration festlegen)",
|
"ALT_CLICK": "Benutzerdefinierter Shell-Befehl (alt_click in Config festlegen)",
|
||||||
"SHOW_HIDE": "Anzeigen, ausblenden, neuzentrieren*",
|
"SHOW_HIDE": "Anzeigen, ausblenden, zentrieren*",
|
||||||
"TOGGLE_DASHBOARD": "Dashboard umschalten",
|
"TOGGLE_DASHBOARD": "Dashboard umschalten",
|
||||||
"SPACE_DRAG": "Playspace-Drag",
|
"SPACE_DRAG": "Playspace ziehen",
|
||||||
"SPACE_ROTATE": "Playspace rotieren",
|
"SPACE_ROTATE": "Playspace rotieren",
|
||||||
"SPACE_RESET": "Playspace zurücksetzen",
|
"SPACE_RESET": "Playspace zurücksetzen",
|
||||||
"CLICK_MODIFIER_RIGHT": "Rechtsklick-Modifikator",
|
"CLICK_MODIFIER_RIGHT": "Rechtsklick-Modifikator",
|
||||||
"CLICK_MODIFIER_MIDDLE": "Mittlere Maustaste-Modifier",
|
"CLICK_MODIFIER_MIDDLE": "Mittelklick-Modifier",
|
||||||
"MOVE_MOUSE": "Maus bewegen (falls standardmäßig deaktiviert)",
|
"MOVE_MOUSE": "Maus bewegen (falls standardmäßig aus)",
|
||||||
"SCROLL": "Scrollen*"
|
"SCROLL": "Scrollen*"
|
||||||
},
|
},
|
||||||
"LEFT": "Links",
|
"LEFT": "Links",
|
||||||
"RIGHT": "Rechts",
|
"RIGHT": "Rechts",
|
||||||
"COMPONENT": "Auslösetyp",
|
"COMPONENT": "Aktivierungsart",
|
||||||
"SUBPATH": "Betätigungskontrolle",
|
"SUBPATH": "Bedienelement",
|
||||||
"THRESHOLD": "Aktivieren, wenn oberer Wert überschritten\nDeaktivieren, wenn unterer Wert unterschritten"
|
"THRESHOLD": "Aktivieren bei Überschreiten des oberen Wertes\nDeaktivieren bei Unterschreiten des unteren Wertes"
|
||||||
},
|
},
|
||||||
|
"BROWSE_ONLINE_CATALOG": "Online-Katalog durchsuchen...",
|
||||||
|
"BROWSE_SKYMAPS": "Skymaps durchsuchen",
|
||||||
|
"CAPTURE_METHOD": "Bildschirmaufnahme-Methode",
|
||||||
|
"CAPTURE_METHOD_HELP": "Ändere dies, wenn du schwarze oder\nfehlerhafte Bildschirme hast",
|
||||||
|
"COLOR_KEYING": "Farbschlüsselung",
|
||||||
|
"COLOR_PALETTE": "Farbpalette",
|
||||||
|
"COLOR_PALETTE_HELP": "Zum Durchsuchen der Farbpaletten klicken.\nFür eigene Paletten siehe Website!",
|
||||||
|
"COLOR_PALETTES": "Farbpaletten",
|
||||||
|
"COLOR_PALETTE_CURRENT": "Aktuelles Thema.",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Eigenes Theme hinzufügen!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Klicken zum Öffnen des Web-Handbuchs.",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "Zum Anwenden dieses Themes klicken.",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS": "PipeWire-Token löschen",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "Bildschirmauswahl beim nächsten Start abfragen",
|
||||||
|
"CLEAR_SAVED_STATE": "Gespeicherten Zustand löschen",
|
||||||
|
"CLEAR_SAVED_STATE_HELP": "Sets & Overlay-Positionen zurücksetzen",
|
||||||
|
"CLICK_FREEZE_TIME_MS": "Klick-Freeze-Zeit (ms)",
|
||||||
|
"CLICK_FREEZE_TIME_MS_HELP": "Hilft bei der Doppelklick-Präzision",
|
||||||
|
"CLOCK_12H": "12-Stunden-Uhr",
|
||||||
|
"CONTROLS": "Steuerung",
|
||||||
|
"DELETE_ALL_CONFIGS": "Konfiguration zurücksetzen",
|
||||||
|
"DELETE_ALL_CONFIGS_HELP": "Alle Konfigurationsdateien aus conf.d entfernen",
|
||||||
|
"DOUBLE_CURSOR_FIX": "Doppelkursor-Fix",
|
||||||
|
"DOUBLE_CURSOR_FIX_HELP": "Aktivieren, wenn zwei Cursor sichtbar sind",
|
||||||
|
"DEFAULT_OVERLAY_SCALE": "Standardgröße der Overlays",
|
||||||
|
"DEFAULT_OVERLAY_SCALE_HELP": "Neue Overlays in dieser Größe spawnen.",
|
||||||
|
"DEFAULT_CURVATURE": "Standard-Overlay-Krümmung",
|
||||||
|
"DEFAULT_OPACITY": "Standard-Overlay-Undurchsichtigkeit",
|
||||||
|
"DEFAULT_POSITIONING": "Standard-Positionierung der Overlays",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "Gilt nur für neue Overlays",
|
||||||
"ENABLED": "Aktiviert",
|
"ENABLED": "Aktiviert",
|
||||||
"INPUT_EMULATION_METHOD": "Methode zur Eingabeemulation",
|
"FEATURES": "Features",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "Versuchen Sie dies zu ändern, falls Maus- oder\nTastatureingaben nicht registriert werden.",
|
"FOCUS_FOLLOWS_MOUSE_MODE": "Mausbewegung bei Trigger-Berührung",
|
||||||
"INPUT_PROFILES": "Eingabesteuerungen ändern",
|
"HANDSFREE_POINTER": "Freisprechmodus",
|
||||||
"INPUT_PROFILES_HELP": "OpenXR-Controller-Eingabebindungen",
|
"HANDSFREE_POINTER_HELP": "Eingabe, wenn keine Motion-Controller verfügbar sind.\nLinkes Zusammenkneifen zum Greifen, rechtes zum Klicken.",
|
||||||
|
"HANDSFREE_ALT_TAB": "Ausrichtung des App-Switchers",
|
||||||
|
"HANDSFREE_ALT_TAB_HELP": "Super+X halten, auf das gewünschte Fenster zielen und dann loslassen, um den Fokus zu wechseln.",
|
||||||
|
"HIDE_GRAB_HELP": "Greifhilfe ausblenden",
|
||||||
|
"HIDE_USERNAME": "Benutzernamen ausblenden",
|
||||||
|
"INPUT_EMULATION_METHOD": "Input-Emulationsmethode",
|
||||||
|
"INPUT_EMULATION_METHOD_HELP": "Hier ändern, falls Maus- oder\nTastatureingaben nicht registriert werden.",
|
||||||
|
"INPUT_CAPTURE_METHOD": "Eingabemethode",
|
||||||
|
"INPUT_CAPTURE_METHOD_HELP": "Ermöglicht die Nutzung physischer Peripheriegeräte in WayVR.\n Super+Z: Eingabe zwischen WayVR und echtem Desktop wechseln\n Super+X: Zwischen WayVR-Apps wechseln",
|
||||||
|
"INPUT_PROFILES": "Eingabebindungen ändern",
|
||||||
|
"INPUT_PROFILES_HELP": "OpenXR-Controller-Belegungen",
|
||||||
|
"INVERT_SCROLL_DIRECTION_X": "Horizontalen Scrollrichtung umkehren",
|
||||||
|
"INVERT_SCROLL_DIRECTION_Y": "Vertikale Scrollrichtung umkehren",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK": "Tastatur-Mittelklick",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK_HELP": "Modifier-Taste bei der Eingabe\nmit dem lila Laser",
|
||||||
|
"KEYBOARD_SOUND_ENABLED": "Tastatursounds",
|
||||||
|
"LANGUAGE": "Sprache",
|
||||||
|
"LEFT_HANDED_MOUSE": "Linkshänder-Maus",
|
||||||
|
"LEFT_HANDED_MOUSE_HELP": "Nutze dies, wenn die Maustasten vertauscht sind",
|
||||||
|
"LONG_PRESS_DURATION": "Langpress-Dauer",
|
||||||
|
"LOOK_AND_FEEL": "Aussehen & Gefühl",
|
||||||
|
"MISC": "Verschiedenes",
|
||||||
|
"NOTIFICATIONS_ENABLED": "Benachrichtigungen aktivieren",
|
||||||
|
"NOTIFICATIONS_SOUND_ENABLED": "Benachrichtigungstöne",
|
||||||
"NOT_SUPPORTED": "Nicht unterstützt",
|
"NOT_SUPPORTED": "Nicht unterstützt",
|
||||||
"ENABLE_WATCH": "Watch aktivieren",
|
"NO_SKYMAPS_FOUND": "Keine Skymaps gefunden",
|
||||||
"SPACE_DRAG": "Space-drag",
|
"OPAQUE_BACKGROUND": "Undurchsichtiger Hintergrund",
|
||||||
|
"OPTION": {
|
||||||
|
"ANCHORED_HELP": "Bewegt sich mit dem Zentrumsmarker. Empfohlen.",
|
||||||
|
"FLOATING_HELP": "Bewegt sich unabhängig, zentriert sich neu.\nLeicht zu verlieren; nicht empfohlen.",
|
||||||
|
"STATIC_HELP": "Bleibt relativ zur Welt an Ort und Stelle.",
|
||||||
|
"AUTO": "Automatisch",
|
||||||
|
"AUTO_HELP": "ScreenCopy GPU, falls unterstützt, \nansonsten PipeWire GPU.",
|
||||||
|
"EYE_ONLY": "Augenlaser",
|
||||||
|
"EYE_PINCH": "Blick + Pinch",
|
||||||
|
"HMD_ONLY": "HMD-Laser",
|
||||||
|
"HMD_PINCH": "HMD + Greifen",
|
||||||
|
"NONE": "Keine",
|
||||||
|
"NONE_INPUT_HELP": "Keine Maus- und Tastatur-Emulation.\nInteraktion mit Bildschirmen nicht möglich.",
|
||||||
|
"NONE_INPUT_CAPTURE_HELP": "Keine Maus- und Tastaturerfassung.\nPhysische Maus oder Tastatur können in\nWayVR gestarteten Apps nicht genutzt werden.",
|
||||||
|
"PIPEWIRE_HELP": "Schnelle GPU-Erfassung,\nStandard auf allen Desktops.",
|
||||||
|
"PW_FALLBACK_HELP": "Langsame Methode mit hoher CPU-Auslastung.\nAusprobieren, falls PipeWire GPU nicht funktioniert",
|
||||||
|
"SCREENCOPY_GPU_HELP": "Schnell, ohne Popups beim Bildschirmausschnitt.\nFunktioniert bei: Hyprland, Niri, River, Sway",
|
||||||
|
"SCREENCOPY_HELP": "Langsam, keine Pop-ups beim Bildschirmteilen.\nFunktioniert mit: Hyprland, Niri, River, Sway",
|
||||||
|
"UINPUT": "Geräteemulation",
|
||||||
|
"UINPUT_HELP": "Nutzt das uinput-Modul zur Geräteemulation.\nFunktioniert auf den meisten Desktops gut.",
|
||||||
|
"EVDEV_HELP": "Eingabegeräte für die exklusive Nutzung erfassen.\nDein Benutzer muss Mitglied der Gruppe \"input\" sein.",
|
||||||
|
"WL_VIRTUAL": "Wayland-virtueller Input",
|
||||||
|
"WL_VIRTUAL_HELP": "Sende Ereignisse an den Wayland-Compositor mittels\nzwlr_virtual_pointer und zwp_virtual_keyboard.\nFunktioniert nur auf einigen Desktops zuverlässig.\nFunktioniert NICHT unter KDE, GNOME oder COSMIC."
|
||||||
|
},
|
||||||
|
"POINTER_ACCELERATION": "Mausbeschleunigung",
|
||||||
|
"POINTER_ACCELERATION_HELP": "An: Adaptive Mausbeschleunigung\nAus: Konstante Geschwindigkeit",
|
||||||
|
"POINTER_LERP_FACTOR": "Zeiger-Glättung",
|
||||||
|
"POINTER_SPEED": "Mausgeschwindigkeit",
|
||||||
|
"REQUIRES_RESTART": "Neustart erforderlich",
|
||||||
|
"RESET_PLAYSPACE": "Playspace zurücksetzen",
|
||||||
|
"RESET_PLAYSPACE_HELP": "Playspace-Versatz zurücksetzen.",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "Playspace-Zentrum speichern",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "Nutze aktuellen Playspace für die Playspace-Reset-Belegung.",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "Playspace-Zentrum zurücksetzen",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "Vorheriges Playspace-Zentrum zurücksetzen.",
|
||||||
|
"RESTART_SOFTWARE": "Software neu starten",
|
||||||
|
"RESTART_SOFTWARE_HELP": "Einstellungen übernehmen, die einen Neustart erfordern",
|
||||||
|
"ROUND_MULTIPLIER": "Abrundung der UI-Kanten",
|
||||||
|
"SCREEN_RENDER_DOWN": "Bildschirm mit niedrigerer Auflösung rendern",
|
||||||
|
"SCREEN_RENDER_DOWN_HELP": "Hilft gegen Treppeneffekte bei hochauflösenden Bildschirmen",
|
||||||
|
"SCROLL_SPEED": "Scrollgeschwindigkeit",
|
||||||
|
"SELECT_VARIANT": "Variante wählen",
|
||||||
|
"SNAP_ANGLE_DEG": "Snap-Winkel für Fenster-Neigung & Rollen",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "Gegriffene Fenster rasten auf der Nick- und Rollachse in diesem Winkel ein.",
|
||||||
|
"ENABLE_WATCH": "Handgelenk-Uhr aktivieren",
|
||||||
|
"SETS_ON_WATCH": "Sets auf Handgelenk-Uhr",
|
||||||
|
"SHOW_WELCOME_SCREEN": "Willkommensbildschirm anzeigen",
|
||||||
|
"SKYBOX": "Skymap",
|
||||||
|
"SKYMAP_ALREADY_DOWNLOADED": "Diese Skymap ist bereits heruntergeladen. Wähle eine Aktion aus.",
|
||||||
|
"SPACE_DRAG": "Playspace",
|
||||||
|
"SPACE_DRAG_MULTIPLIER": "Space-Drag-Multiplikator",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "Overlays bei Playspace-Verschiebung zurücklassen",
|
||||||
|
"SPACE_DRAG_UNLOCKED": "Space-drag auf allen Achsen erlauben",
|
||||||
"SPACE_GRAVITY_DAMPING": "Dämpfung",
|
"SPACE_GRAVITY_DAMPING": "Dämpfung",
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "Künstlicher Widerstand, um die Bewegung zu verlangsamen. 0,1 - hoher Widerstand, 1,0 - kein Widerstand",
|
"SPACE_GRAVITY_DAMPING_HELP": "Künstlicher Widerstand zur Verlangsamung der Bewegung. 0,1 – hoher Widerstand, 1,0 – kein Widerstand",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH": "Wurfstärke",
|
"SPACE_GRAVITY_FLING_STRENGTH": "Schleuderstärke",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Intensitätsmultiplikator der Schwerkraft-Abstoßungskraft nach dem Space-drag.\n0.0 - gar keine Bewegung, 2.0 - doppelte Intensität",
|
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Intensitätsmultiplikator der Gravitationskraft nach dem Space-drag.\n0.0 - gar keine Bewegung, 2.0 - doppelte Intensität",
|
||||||
"SPACE_GRAVITY_GRAVITY": "Gravitation",
|
"SPACE_GRAVITY_GRAVITY": "Gravitation",
|
||||||
"SPACE_GRAVITY_GRAVITY_HELP": "Betrag der Abwärtskraft. 0.0 - keine Schwerkraft",
|
"SPACE_GRAVITY_GRAVITY_HELP": "Stärke der Abwärtskraft. 0.0 - keine Schwerkraft",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION": "Bodenreibung",
|
"SPACE_GRAVITY_GROUND_FRICTION": "Bodenreibung",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Das Ausmaß der Reibung, das Sie verlangsamt, wenn Sie den Boden berühren.\n0.0 - keine Reibung (wie auf Eis), 1.0 - raue Oberfläche",
|
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Reibung beim Kontakt mit dem Boden.\n0,0 - keine Reibung (wie auf Eis), 1,0 - raue Oberfläche",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "Bodenhöhe",
|
"SPACE_GRAVITY_FLOOR_HEIGHT": "Bodenhöhe",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Die Y-Position, an der sich der Boden befindet. Die Schwerkraft wird gestoppt, wenn Sie diese Höhe erreichen.",
|
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Die Y-Position des Bodens. Hier endet die Wirkung der Gravitation.",
|
||||||
"SAVE": "Speichern",
|
"SPACE_ROTATE_UNLOCKED": "Playspace-Rotation auf allen Achsen erlauben",
|
||||||
"CANCEL": "Abbrechen",
|
"TROUBLESHOOTING": "Fehlerbehebung",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UI-Gradientenintensität",
|
||||||
|
"UPRIGHT_SCREEN_FIX": "Bildschirm-Ausrichtung korrigieren",
|
||||||
|
"UPRIGHT_SCREEN_FIX_HELP": "Korrgiert aufrecht ausgerichtete Bildschirme bei einigen Desktops",
|
||||||
|
"USE_PASSTHROUGH": "Passthrough aktivieren",
|
||||||
|
"USE_PASSTHROUGH_HELP": "Passthrough zulassen, falls die XR-Runtime dies unterstützt",
|
||||||
|
"USE_SKYBOX": "Skymap anzeigen",
|
||||||
|
"USE_SKYBOX_HELP": "Skymap anzeigen, wenn keine Scene-App oder Passthrough aktiv ist",
|
||||||
|
"WATCH_VIEW_ANGLE": "Sichtwinkel der Handgelenk-Uhr",
|
||||||
|
"WATCH_VIEW_ANGLE_HELP": "Steuere, wie die Uhr ausblendet",
|
||||||
"WHISPER": {
|
"WHISPER": {
|
||||||
"NEED_TO_DOWNLOAD_MODEL": "Das ausgewählte Modell muss heruntergeladen werden.\nJetzt herunterladen?",
|
"NEED_TO_DOWNLOAD_MODEL": "Das ausgewählte Modell muss heruntergeladen werden.\nJetzt herunterladen?",
|
||||||
"REMOVE_UNUSED_MODELS": "Sie schalten die Sprache-zu-Text-Funktion aus.\nMöchten Sie die heruntergeladenen Whisper-Modelle entfernen, um Speicherplatz freizugeben?"
|
"REMOVE_UNUSED_MODELS": "Du deaktivierst die Spracherkennungsfunktion.\nMöchtest du die heruntergeladenen Whisper-Modelle entfernen, um Speicherplatz freizugeben?"
|
||||||
},
|
},
|
||||||
"WHISPER_MODEL": "Sprach-zu-Text-Modell",
|
"WHISPER_MODEL": "Sprache-zu-Text-Modell",
|
||||||
"WHISPER_MODEL_HELP": "Zu verwendendes Whisper-Modell.\nGrößere Modelle liefern genauere\nErgebnisse, verbrauchen jedoch mehr VRAM."
|
"WHISPER_MODEL_HELP": "Zu verwendendes Whisper-Modell.\nGrößere Modelle liefern präzisere\nErgebnisse, verbrauchen aber mehr VRAM.",
|
||||||
|
"GRID_OPACITY": "Bodenraster-Deckkraft",
|
||||||
|
"GRID_OPACITY_HELP": "Deckkraft des Bodengitters, wenn die Skymap aktiviert ist",
|
||||||
|
"XWAYLAND_BY_DEFAULT": "Apps standardmäßig im Kompatibilitätsmodus starten",
|
||||||
|
"SAVE": "Speichern",
|
||||||
|
"CANCEL": "Abbrechen"
|
||||||
},
|
},
|
||||||
"HELLO": "Hallo!",
|
"APPLICATION_LAUNCHER": "Programmstarter",
|
||||||
"AUDIO": {
|
|
||||||
"VOLUME": "Lautstärke",
|
|
||||||
"SETTINGS": "Audioeinstellungen",
|
|
||||||
"AUTO_SWITCH_TO_VR_AUDIO": "Automatisch auf VR-Audio umschalten",
|
|
||||||
"SPEAKERS": "Lautsprecher",
|
|
||||||
"MICROPHONES": "Mikrofone",
|
|
||||||
"CARDS": "Sound-Karten",
|
|
||||||
"SELECT_AUDIO_CARD_PROFILE": "Wählen Sie das Sound-Kartenprofil",
|
|
||||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Keine VR-Lautsprecher gefunden. Schalten Sie diese manuell um.",
|
|
||||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Kein VR-Mikrofon gefunden. Schalten Sie es manuell um.",
|
|
||||||
"FAILED_TO_SWITCH_MICROPHONE": "Fehler beim Wechseln des Mikrofons",
|
|
||||||
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon erfolgreich umgeschaltet",
|
|
||||||
"SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich umgeschaltet"
|
|
||||||
},
|
|
||||||
"ACTIONS": {
|
|
||||||
"RECENTER_PLAYSPACE": "Playspace neu zentrieren"
|
|
||||||
},
|
|
||||||
"POPUP_ADD_DISPLAY": {
|
|
||||||
"RESOLUTION": "Auflösung"
|
|
||||||
},
|
|
||||||
"WIDTH": "Breite",
|
|
||||||
"HEIGHT": "Höhe",
|
|
||||||
"HIDE": "Verbergen",
|
|
||||||
"REMOVE": "Entfernen",
|
|
||||||
"SHOW": "Anzeigen",
|
|
||||||
"FAILED_TO_LAUNCH_APPLICATION": "Fehler beim Starten der Anwendung:",
|
|
||||||
"APPLICATION_STARTED": "Anwendung gestartet",
|
"APPLICATION_STARTED": "Anwendung gestartet",
|
||||||
|
"APPLICATIONS": "Anwendungen",
|
||||||
|
"AUDIO": {
|
||||||
|
"AUTO_SWITCH_TO_VR_AUDIO": "Automatisch auf VR-Audio umschalten",
|
||||||
|
"CARDS": "Soundkarten",
|
||||||
|
"FAILED_TO_SWITCH_MICROPHONE": "Mikrofonwechsel fehlgeschlagen",
|
||||||
|
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon erfolgreich eingestellt",
|
||||||
|
"MICROPHONES": "Mikrofone",
|
||||||
|
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Kein VR-Mikrofon gefunden. Manuell umschalten.",
|
||||||
|
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Keine VR-Lautsprecher gefunden. Manuell umschalten.",
|
||||||
|
"SELECT_AUDIO_CARD_PROFILE": "Soundkartenprofil wählen",
|
||||||
|
"SETTINGS": "Audio-Einstellungen",
|
||||||
|
"SPEAKERS": "Lautsprecher",
|
||||||
|
"SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich eingestellt",
|
||||||
|
"VOLUME": "Lautstärke"
|
||||||
|
},
|
||||||
"CLOSE_WINDOW": "Fenster schließen",
|
"CLOSE_WINDOW": "Fenster schließen",
|
||||||
|
"CREATION_DATE": "Erstellungsdatum",
|
||||||
|
"DEBUG_INFO": "Debug-Infos",
|
||||||
|
"DISPLAY_BRIGHTNESS": "Displayhelligkeit",
|
||||||
|
"DONATE": {
|
||||||
|
"SUPPORT_US": "Unterstützt uns",
|
||||||
|
"DESCRIPTION": "Wir sind ein kleines Team aus 2 Entwicklern, die WayVR in ihrer Freizeit bauen. Wenn dir die Software gefällt, unterstütze uns bitte – jede Spende hilft uns dabei, weiterzumachen.",
|
||||||
|
"THANK_YOU_WAYVR": "Danke vom WayVR-Team!",
|
||||||
|
"BUTTON_TOOLTIP": "Via Open Collective spenden",
|
||||||
|
"CURRENT_SUPPORTERS": "Aktuelle Unterstützer",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Unterstützt von {USER}|Besonderer Dank an {USER}|Gesponsert von {USER}|Ermöglicht durch {USER}|Getragen von Community-Mitgliedern wie {USER}|Mit Hilfe von {USER}|Aufrechterhalten durch {USER}|Ein Beitrag von {USER}|Finanziert durch {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kaffee spendiert von {USER}|Angetrieben von {USER}|Ein großes Shoutout an {USER}!|{USER} hält uns am Laufen|Mit {USER} wachsen wir weiter|{USER} hält die Server stabil|In voller Dankbarkeit gegenüber {USER}|Power-up durch {USER}|Unterstützt von Freunden wie {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Unterstützt von Legenden wie {USER}|Koffein-Zufuhr gesichert durch {USER}|Eine echte Legende: {USER}|Unser Held des Tages: {USER}|Ein absoluter Superstar: {USER}|Bezahlt gerade die Stromrechnung: {USER}|Der Retter unserer Nerven: {USER}|Der Ruhepol im Chaos: {USER}|Kaffee-zu-Code-Konverter: {USER}|Hält die Production stabil: {USER}|Die eine und einzige(r): {USER}|Bezwinger des dmabuf-Buffers: {USER}"
|
||||||
|
},
|
||||||
|
"DOWNLOAD": "Herunterladen",
|
||||||
|
"DOWNLOADER": "Downloader",
|
||||||
|
"WELCOME": {
|
||||||
|
"ALL_SET": "Alles bereit!",
|
||||||
|
"BASICS": "Diese Grundlagen ermöglichen dir einen einfachen Start mit WayVR.",
|
||||||
|
"CENTER_MARKER": "Die Zentrierungsmarkierung erscheint beim Recentrieren vor dir. Platziere Overlays darum herum!",
|
||||||
|
"DOUBLE_PRESS_TO_TOGGLE": "Drücke B (beim Index) oder Y (bei Meta) doppelt, um dein Set anzuzeigen, neu zu zentrieren oder auszublenden. Probier es jetzt aus.",
|
||||||
|
"FEATURES_DOCUMENTATION": "Es gibt viele weitere anpassbare Funktionen. Weitere Informationen findest du in der Dokumentation unter",
|
||||||
|
"FINISH_TUTORIAL": "Tutorial beenden",
|
||||||
|
"GRAB_BOTH_HANDS": "Greif mit beiden Händen zu, wenn du ein bestimmtes Overlay in deinem Set verschieben willst.",
|
||||||
|
"GRAB_ONE_HAND": "Greife mit einer Hand zu, um dein Set zu bewegen.",
|
||||||
|
"GREETING": "Hallo!",
|
||||||
|
"GUIDE_INTRO": "Lass uns dich durch deine ersten Schritte führen.",
|
||||||
|
"LASER_COLORS": "Laserfarben",
|
||||||
|
"LASER_FUNCTIONALITY": "Vieles in WayVR hängt davon ab, welche Laserfarbe zur Interaktion mit einem UI-Element genutzt wird. Du musst die Schaltflächen nicht drücken, einfach nur berühren!",
|
||||||
|
"LAST_PAGE_INFO": "Dieses Tutorial wird nicht mehr angezeigt, sobald du die letzte Seite erreicht hast.",
|
||||||
|
"LOOK_AT_LEFT_WRIST": "Schau auf dein linkes Handgelenk. Das ist deine Handgelenk-Uhr.",
|
||||||
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Mittelklick-Modus: Lilafarbener Laser",
|
||||||
|
"MOVING_YOUR_SET": "Set verschieben",
|
||||||
|
"NEXT_BUTTON": "Drücke unten auf „Weiter“, um zu starten.",
|
||||||
|
"REGULAR_MODE_BLUE_LASER": "Normalmodus: Blauer Laser",
|
||||||
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Positioniere dieses Fenster neu, indem du die Grip-Taste deines Controllers benutzt.",
|
||||||
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "Rechtsklick-Modus: Oranger Laser",
|
||||||
|
"THANKS_FOR_INSTALLING": "Vielen Dank für die Installation von WayVR!",
|
||||||
|
"WATCH": "Handgelenk-Uhr",
|
||||||
|
"WORKING_SET": "Aktives Set"
|
||||||
|
},
|
||||||
|
"DOWNLOAD_AGAIN": "Erneut herunterladen",
|
||||||
|
"DOWNLOADING_FILE": "Datei wird heruntergeladen...",
|
||||||
|
"FAILED_TO_LAUNCH_APPLICATION": "Starten der Anwendung fehlgeschlagen:",
|
||||||
|
"GAME_LAUNCHED": "Spiel gestartet",
|
||||||
"GAME_LIST": {
|
"GAME_LIST": {
|
||||||
"NO_GAMES_FOUND": "Keine Spiele gefunden",
|
"NO_GAMES_FOUND": "Keine Spiele gefunden",
|
||||||
"RUNNING_GAMES_LIST": "Liste der laufenden Spiele"
|
"RUNNING_GAMES_LIST": "Liste der laufenden Spiele"
|
||||||
},
|
},
|
||||||
"TERMINATE_PROCESS": "Prozess beenden",
|
"GAMES": "Spiele",
|
||||||
"GAME_LAUNCHED": "Spiel gestartet",
|
"GENERAL_SETTINGS": "Allgemeine Einstellungen",
|
||||||
"APP_LAUNCHER": {
|
"GETTING_STARTED": "Erste Schritte",
|
||||||
"MODE": {
|
"HEIGHT": "Höhe",
|
||||||
"NATIVE": "Nativer Modus",
|
"HELLO": "Hallo!",
|
||||||
"CAGE": "Kompatibilitätsmodus (Cage)"
|
"HELLO_USER": "Hallo, {USER}!",
|
||||||
},
|
"HIDE": "Ausblenden",
|
||||||
"RES_TITLE": "Auflösung",
|
"HOME_SCREEN": "Home",
|
||||||
"ASPECT_TITLE": "Seitenverhältnis",
|
"MODIFICATION_DATE": "Änderungsdatum",
|
||||||
"ASPECT": {
|
"MONADO_RUNTIME": "Monado Runtime",
|
||||||
"WIDE": "Breit",
|
"LOADING": "Lädt...",
|
||||||
"SEMI_WIDE": "Halb-breit",
|
"POPUP_ADD_DISPLAY": {
|
||||||
"SQUARE": "Quadratisch",
|
"RESOLUTION": "Auflösung"
|
||||||
"SEMI_TALL": "Halbhoch",
|
},
|
||||||
"TALL": "Hoch"
|
"PROCESS": {
|
||||||
},
|
"FORCE_KILL": "Sofort beenden",
|
||||||
"POS_TITLE": "Positionierung",
|
"STOP": "Beenden"
|
||||||
"POS": {
|
|
||||||
"FLOATING": "Schwebend",
|
|
||||||
"ANCHORED": "Verankert",
|
|
||||||
"STATIC": "Statisch",
|
|
||||||
"FLOATING_HELP": "Bewegt sich unabhängig, zentriert sich bei Anzeige neu.",
|
|
||||||
"ANCHORED_HELP": "Bleibt relativ zur Mittelmarkierung an Ort und Stelle.",
|
|
||||||
"STATIC_HELP": "Keine Set zugeordnet. Wird nicht zentriert."
|
|
||||||
},
|
|
||||||
"AUTOSTART": "Automatisch beim Start ausführen",
|
|
||||||
"LAUNCH": "Starten"
|
|
||||||
},
|
},
|
||||||
"DISPLAY_BRIGHTNESS": "Bildschirmhelligkeit",
|
|
||||||
"PROCESS_LIST": "Prozessliste",
|
"PROCESS_LIST": "Prozessliste",
|
||||||
"REFRESH": "Aktualisieren",
|
"REFRESH": "Aktualisieren",
|
||||||
"PROCESS": {
|
"REMOVE": "Entfernen",
|
||||||
"STOP": "Stopp",
|
|
||||||
"FORCE_KILL": "Erzwinge Beenden"
|
|
||||||
},
|
|
||||||
"DEBUG_INFO": "Debug-Informationen",
|
|
||||||
"CREATION_DATE": "Erstellungsdatum",
|
|
||||||
"DOWNLOADER": "Downloader",
|
|
||||||
"DOWNLOAD_AGAIN": "Erneut herunterladen",
|
|
||||||
"DOWNLOADING_FILE": "Datei wird heruntergeladen...",
|
|
||||||
"GETTING_STARTED": "Erste Schritte",
|
|
||||||
"MODIFICATION_DATE": "Änderungsdatum",
|
|
||||||
"LOADING": "Laden...",
|
|
||||||
"APPLY": "Anwenden",
|
"APPLY": "Anwenden",
|
||||||
"RELOAD_FROM_DISK": "Von Festplatte neu laden",
|
"RELOAD_FROM_DISK": "Von Festplatte neu laden",
|
||||||
|
"SETTINGS": "Einstellungen",
|
||||||
|
"SHOW": "Anzeigen",
|
||||||
"TARGET_PATH": "Zielpfad",
|
"TARGET_PATH": "Zielpfad",
|
||||||
|
"TERMINATE_PROCESS": "Prozess beenden",
|
||||||
"VERSION": "Version",
|
"VERSION": "Version",
|
||||||
"DONATE": {
|
"WIDTH": "Breite",
|
||||||
"SUPPORT_US": "Unterstütze uns",
|
"PINNED_APPS": "Angeheftete Anwendungen",
|
||||||
"DESCRIPTION": "Wir sind ein kleines Team aus zwei Entwicklern, die WayVR in ihrer Freizeit bauen. Wenn Ihnen die Nutzung dieser Software Spaß macht, unterstützen Sie uns bitte – jede Spende hilft uns, weiterzumachen.",
|
"SAVED_TO_FAVOURITES": "Zu den angehefteten Anwendungen hinzugefügt",
|
||||||
"BUTTON_TOOLTIP": "Spenden über Open Collective",
|
"ADD_TO_FAVOURITES": "Zu angehefteten Anwendungen hinzufügen",
|
||||||
"CURRENT_SUPPORTERS": "Aktuelle Unterstützer",
|
"ADD_TO_FAVOURITES_HINT": "Voreinstellung speichern und an die App-Schublade anheften",
|
||||||
"THANK_YOU_WAYVR": "Vielen Dank vom WayVR-Team!"
|
"REMOVE_FROM_FAVOURITES": "Aus angehefteten Anwendungen entfernen",
|
||||||
},
|
"EMPTY": "Leer"
|
||||||
"WELCOME": {
|
|
||||||
"ALL_SET": "Du bist startklar!",
|
|
||||||
"BASICS": "Diese Grundlagen ermöglichen Ihnen einen einfachen Einstieg in die Nutzung von WayVR.",
|
|
||||||
"CENTER_MARKER": "Der Mittelpunkt-Marker bestimmt das Zentrum Ihres Sets.",
|
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "Drücken Sie zweimal B (auf Index) oder Y (auf Meta), um die Sichtbarkeit Ihres Arbeitsbereichs umzuschalten. Probieren Sie es jetzt aus.",
|
|
||||||
"FEATURES_DOCUMENTATION": "Es gibt viele weitere Funktionen, die es wert sind, angepasst zu werden. Weitere Informationen finden Sie in der Dokumentation unter",
|
|
||||||
"FINISH_TUTORIAL": "Tutorial beenden",
|
|
||||||
"GRAB_BOTH_HANDS": "Greifen Sie es mit beiden Händen, wenn Sie ein bestimmtes Overlay in Ihrem Set bewegen möchten.",
|
|
||||||
"GRAB_ONE_HAND": "Greife es mit einer Hand, um dein Set zu bewegen.",
|
|
||||||
"GREETING": "Hallo!",
|
|
||||||
"GUIDE_INTRO": "Lassen Sie sich durch Ihre ersten Schritte führen.",
|
|
||||||
"LASER_COLORS": "Laserfarben",
|
|
||||||
"LASER_FUNCTIONALITY": "Ein Großteil der Funktionalität in WayVR hängt davon ab, welche Laserfarbe verwendet wird, um mit einem UI-Element zu interagieren. Sie müssen diese Schaltflächen nicht drücken, berühren Sie sie einfach!",
|
|
||||||
"LAST_PAGE_INFO": "Dieses Tutorial wird nicht mehr angezeigt, sobald du die letzte Seite erreicht hast.",
|
|
||||||
"LOOK_AT_LEFT_WRIST": "Schau auf dein linkes Handgelenk. Das ist deine Watch.",
|
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Mittlere Maustaste-Modus: Lila Laser",
|
|
||||||
"MOVING_YOUR_SET": "Ihr Set wird verschoben",
|
|
||||||
"NEXT_BUTTON": "Drücke die Schaltfläche „Weiter“ unten, um zu beginnen.",
|
|
||||||
"REGULAR_MODE_BLUE_LASER": "— Regulärer Modus: Blauer Laser",
|
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Positionieren Sie dieses Fenster neu, indem Sie die Greifaktion Ihres Controllers verwenden.",
|
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Rechtsklick-Modus: Oranger Laser",
|
|
||||||
"THANKS_FOR_INSTALLING": "Vielen Dank für die Installation von WayVR!",
|
|
||||||
"WATCH": "Watch",
|
|
||||||
"WORKING_SET": "Arbeits-Set"
|
|
||||||
},
|
|
||||||
"DOWNLOAD": "Herunterladen"
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,339 @@
|
||||||
|
DEFINITIONS.ANCHORED,Anchored,"A movement option that makes this window move together with the rest of the workspace. Emphasize the ""moving together"" part as opposed to ""not moving at all""."
|
||||||
|
DEFINITIONS.FLOATING,Floating,A movement option that lets this window float freely.
|
||||||
|
DEFINITIONS.STATIC,Static,"A movement option that keeps this window in place relative to the world origin. Emphasize the ""not moving at all"" part, as opposed to the ""moving together"" option which was previously translated as ${DEFINITIONS.ANCHORED}."
|
||||||
|
DEFINITIONS.SET,Set,A desktop workspace consisting of multiple windows.
|
||||||
|
DEFINITIONS.WATCH,Watch,Name of the small utility window that hovers around the user's wrist.
|
||||||
|
DEFINITIONS.DASHBOARD,Dashboard,Name of the window that acts as the main menu / control panel of the application.
|
||||||
|
DEFINITIONS.EDIT_MODE,Edit Mode,Name of the mode that allows the user to make various tweaks to the current workspace and its windows.
|
||||||
|
DEFINITIONS.SETTINGS,Settings,The title of the settings panel.
|
||||||
|
DEFINITIONS.KEYBOARD,Keyboard,Name of the virtual keyboard
|
||||||
|
DEFINITIONS.TASKBAR,Taskbar,"A long panel showing currently active programs & windows, workspaces and a clock."
|
||||||
|
DEFINITIONS.FEATURES,Features,The section title of the section panel that deals with software features.
|
||||||
|
DEFINITIONS.OVERLAY,Overlay,"An overlay window inside VR, similar to a ""desktop window"". Consider it a technical term."
|
||||||
|
DEFINITIONS.SKYMAP,Skymap,A 360 degree background image that surrounds the user.
|
||||||
|
DEFINITIONS.PLAYSPACE,Playspace,The VR play space that the user can adjust in different way. Technical term.
|
||||||
|
DEFINITIONS.D_PAD,D-pad ,Directional pad on a modern game controller. Technical term.
|
||||||
|
ACTIONS.RECENTER_PLAYSPACE,Re-center playspace,"Tooltip on a button (with recenter icon) in the bottom-left of the VR dashboard. The button resets the user's tracked playspace to the current physical location. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_LAUNCHER.ASPECT.SEMI_TALL,Semi-tall,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 2:3 vertical aspect ratio. Tooltip shows ""2:3""."
|
||||||
|
APP_LAUNCHER.ASPECT.SEMI_WIDE,Semi-wide,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 3:2 aspect ratio. Tooltip shows ""3:2""."
|
||||||
|
APP_LAUNCHER.ASPECT.SQUARE,Square,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 1:1 aspect ratio. Tooltip shows ""1:1""."
|
||||||
|
APP_LAUNCHER.ASPECT.TALL,Tall,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 9:16 vertical aspect ratio. Tooltip shows ""9:16""."
|
||||||
|
APP_LAUNCHER.ASPECT.WIDE,Wide,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 16:9 aspect ratio (standard widescreen). Tooltip shows ""16:9""."
|
||||||
|
APP_LAUNCHER.ASPECT_TITLE,Aspect,"Section header label above a row of 5 radio buttons (Wide, Semi-wide, Square, Semi-tall, Tall) in the App Launcher panel. Controls the window aspect ratio for the selected app."
|
||||||
|
APP_LAUNCHER.AUTOSTART,Run automatically on startup,"Label on a checkbox in the App Launcher panel. When checked, the selected app will launch automatically when the Dash compositor starts."
|
||||||
|
APP_LAUNCHER.LAUNCH,Launch,Label on the primary (blue/primary color) button at the bottom of the App Launcher panel. Launches the selected app with the configured settings. Has a play icon next to it.
|
||||||
|
APP_LAUNCHER.MODE.CAGE,Compatibility mode (Cage),"Radio button option in the App Launcher panel's mode selector (next to ""Native mode""). Sets the app to run in Cage compatibility mode."
|
||||||
|
APP_LAUNCHER.MODE.NATIVE,Native mode,"Radio button option (default/checked) in the App Launcher panel's mode selector (next to ""Compatibility mode (Cage)""). Sets the app to run in native Wayland mode."
|
||||||
|
APP_LAUNCHER.RES_TITLE,Resolution,"Section header label in the App Launcher panel above a row of 4 radio buttons (1440p, 1080p, 720p, 480p). Controls the rendering resolution for the selected app."
|
||||||
|
APP_SETTINGS.ALLOW_SLIDING,Stick interaction during grab,Checkbox label in Settings > Features tab. Toggles whether analog stick input works while an overlay is grabbed/moved.
|
||||||
|
APP_SETTINGS.ANIMATION_SPEED,UI Animation speed,Slider label in Settings > Look & Feel tab. Controls the speed of UI transition animations (range 0.5-5.0).
|
||||||
|
APP_SETTINGS.AUTOSTART_APPS,Apps to run on startup,Category header in Settings. Label for the section listing apps configured to auto-launch on WayVR startup.
|
||||||
|
APP_SETTINGS.BLOCK_GAME_INPUT,Block game input,"Checkbox label in Settings > Features tab. When enabled, blocks all in-game input when an overlay is hovered."
|
||||||
|
APP_SETTINGS.BLOCK_GAME_INPUT_HELP,Blocks all input when an overlay is hovered,Tooltip text appearing next to the Block game input checkbox in Settings > Features.
|
||||||
|
APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH,Ignore watch when blocking input,"Checkbox label in Settings > Features tab. When enabled, hovering the wrist watch does not block game input. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP,Do not block input when watch is hovered,"Tooltip text next to the Ignore watch when blocking input checkbox. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION,Block poses when interacting with keyboard,Checkbox label in Settings > Features tab. Blocks game pose input when the on-screen keyboard is hovered (requires Block game input enabled).
|
||||||
|
APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP,Blocks the game from receiving poses when the keyboard is hovered and 'Block game input' is enabled,Tooltip explaining the Block poses when interacting with keyboard checkbox.
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.CLICK,Click,Dropdown option in the controller bindings editor. Selects the Click component of a controller input.
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.FORCE,Force,Dropdown option in the controller bindings editor. Selects the Force analog component (e.g. how hard a trigger is pressed).
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.TOUCH,Touch,Dropdown option in the controller bindings editor. Selects the Touch component (whether a button is merely touched vs pressed).
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.VALUE,Value,Dropdown option in the controller bindings editor. Selects the raw Value analog output of a component.
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.PROXIMITY,Proximity,Dropdown option in the controller bindings editor. Selects the Proximity component (distance of controller from head/hand).
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.X_AXIS,X axis,"Dropdown option in the controller bindings editor. Selects the X-axis analog value (e.g. thumbstick X, trackpad X)."
|
||||||
|
APP_SETTINGS.BINDINGS.COMP.Y_AXIS,Y axis,"Dropdown option in the controller bindings editor. Selects the Y-axis analog value (e.g. thumbstick Y, trackpad Y)."
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.BUMPER,Bumper,Dropdown option in the bindings editor. Maps to the Bumper controller subpath (upper shoulder button).
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.DPAD_UP,D-pad Up,"Dropdown option in the bindings editor. Maps to the D-pad up direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}""."
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.DPAD_DOWN,D-pad Down,"Dropdown option in the bindings editor. Maps to the D-pad down direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}"". ""D-pad Up"" was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}""."
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.DPAD_LEFT,D-pad Left,"Dropdown option in the bindings editor. Maps to the D-pad left direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}"". ""D-pad Up"" was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}""."
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.DPAD_RIGHT,D-pad Right,"Dropdown option in the bindings editor. Maps to the D-pad right direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}"". ""D-pad Up"" was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}""."
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.JOYSTICK,Joystick,Dropdown option in the bindings editor. Maps to the joystick subpath.
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.MENU,Menu,Dropdown option in the bindings editor. Maps to the Menu controller button.
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.SHOULDER,Shoulder,Dropdown option in the bindings editor. Maps to the Shoulder subpath (shoulder strap button).
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.SQUEEZE,Grip,Dropdown option in the bindings editor. Maps to the Squeeze component (controller grip action).
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.SYSTEM,System,Dropdown option in the bindings editor. Maps to the System controller subpath.
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.THUMBREST,Thumbrest,Dropdown option in the bindings editor. Maps to the thumbrest touch sensor.
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.THUMBSTICK,Thumbstick,"Dropdown option in the bindings editor. Maps to the thumbstick subpath. Different from ""Joystick"" which was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.JOYSTICK}""."
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.TRACKPAD,Trackpad,Dropdown option in the bindings editor. Maps to the trackpad subpath.
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.TRIGGER,Trigger,Dropdown option in the bindings editor. Maps to the trigger subpath.
|
||||||
|
APP_SETTINGS.BINDINGS.TYPE.VIEW,View,Dropdown option in the bindings editor. Maps to the View controller button.
|
||||||
|
APP_SETTINGS.BINDINGS.CLICK.ANY,Any,Dropdown option in the bindings editor. Selects any press click type (no double/triple tap requirement).
|
||||||
|
APP_SETTINGS.BINDINGS.CLICK.DOUBLE,Double-tap,Dropdown option in the bindings editor. Requires a double-tap on the selected button/component.
|
||||||
|
APP_SETTINGS.BINDINGS.CLICK.TRIPLE,Triple-tap,Dropdown option in the bindings editor. Requires a triple-tap on the selected button/component.
|
||||||
|
APP_SETTINGS.BINDINGS.CLICK.TYPE,Tap count,Tooltip for the click-type dropdown in the bindings editor. Indicates this dropdown controls how many taps are required.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.CLICK,Click*,Label for the click action row in the controller bindings editor. The asterisk indicates it may have modifiers. Leave the '*' at the end.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.GRAB,Grab*,Label for the grab action row in the bindings editor. Maps to the controller grab/grip action. Leave the '*' at the end.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.ALT_CLICK,Custom shell exec (set alt_click in config),Label for the alt_click action row in the bindings editor. Triggers a custom shell command defined in config.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.SHOW_HIDE,"Show, hide, recenter*",Label for the show_hide action row. Toggles overlay visibility and recenters the set. Leave the '*' at the end.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.TOGGLE_DASHBOARD,Toggle dashboard,Label for the toggle_dashboard action row. Opens or closes the WayVR dashboard.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.SPACE_DRAG,Playspace drag,"Label for the space_drag action row. Allows dragging the entire playspace/set of overlays. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.SPACE_ROTATE,Playspace rotate,"Label for the space_rotate action row. Allows rotating the entire playspace/set. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.SPACE_RESET,Playspace reset,"Label for the space_reset action row. Resets playspace to the original state. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_RIGHT,Right-click modifier,Label for the click_modifier_right action row. Maps a controller input to act as a right-click modifier.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_MIDDLE,Middle-click modifier,Label for the click_modifier_middle action row. Maps a controller input to act as a middle-click modifier.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.MOVE_MOUSE,Move mouse (if off by default),Label for the move_mouse action row. Maps controller input to mouse movement.
|
||||||
|
APP_SETTINGS.BINDINGS.ACTION.SCROLL,Scroll*,Label for the scroll action row. Maps controller input to scrolling. Leave the '*' at the end.
|
||||||
|
APP_SETTINGS.BINDINGS.LEFT,Left,Label in the bindings editor. Refers to the left controller/hand configuration.
|
||||||
|
APP_SETTINGS.BINDINGS.RIGHT,Right,Label in the bindings editor. Refers to the right controller/hand configuration.
|
||||||
|
APP_SETTINGS.BINDINGS.COMPONENT,Actuation type,"Tooltip for the component dropdown in the bindings editor. Asks user to select what type of actuation (click, touch, axis, etc.)."
|
||||||
|
APP_SETTINGS.BINDINGS.SUBPATH,Actuating control,Tooltip for the subpath dropdown in the bindings editor. Asks user to select which controller button/stick/trackpad to bind.
|
||||||
|
APP_SETTINGS.BINDINGS.THRESHOLD,"Activate when above upper value
|
||||||
|
Deactivate when below lower value",Tooltip for the threshold slider in the bindings editor. Explains the two-value threshold range for analog inputs.
|
||||||
|
APP_SETTINGS.BROWSE_ONLINE_CATALOG,Browse online catalog...,Button label in the color palettes popup. Opens a web browser to the WayVR online catalog.
|
||||||
|
APP_SETTINGS.BROWSE_SKYMAPS,Browse skymaps,"Button label in Settings > Skybox tab. Opens the skymap browser/list. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.CAPTURE_METHOD,Screen capture method,"Dropdown label in Settings > Miscellaneous tab. Selects the method for capturing the desktop screen (PipeWire, ScreenCopy, etc.)."
|
||||||
|
APP_SETTINGS.CAPTURE_METHOD_HELP,"Try changing this if you are
|
||||||
|
experiencing black or glitchy screens",Tooltip for the Wayland screen capture dropdown in Miscellaneous settings.
|
||||||
|
APP_SETTINGS.COLOR_KEYING,Color keying,Setting in the look-and-feel / color palette section. Enables or configures chroma-key style color filtering.
|
||||||
|
APP_SETTINGS.COLOR_PALETTE,Color palette,Button label in Settings > Look & Feel tab. Opens the color palette selection popup.
|
||||||
|
APP_SETTINGS.COLOR_PALETTE_HELP,"Click to browse color palettes.
|
||||||
|
To create custom ones, see website!",Tooltip for the Color palette button.
|
||||||
|
APP_SETTINGS.COLOR_PALETTES,Color palettes,Category/header label in the color palette popup.
|
||||||
|
APP_SETTINGS.COLOR_PALETTE_CURRENT,Currently active theme.,Label or tooltip showing which color palette is currently applied.
|
||||||
|
APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL,Add your own custom theme!,Button/label in the color palette popup for adding a custom theme via URL.
|
||||||
|
APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL2,Click to open web manual.,"Secondary label/button next to the custom URL input, linking to the web manual."
|
||||||
|
APP_SETTINGS.COLOR_PALETTE_ACTIVATE,Click to use this theme.,Tooltip or button label on a palette card to apply/activate that theme.
|
||||||
|
APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS,Clear PipeWire tokens,Button label in Settings > Troubleshooting tab. Clears stored PipeWire screen-selection tokens so the user is prompted again on next start.
|
||||||
|
APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS_HELP,Prompt for screen selection on next start,Tooltip explaining what clearing PipeWire tokens does.
|
||||||
|
APP_SETTINGS.CLEAR_SAVED_STATE,Clear saved state,Button label in Settings > Troubleshooting tab. Resets overlay positions and set placements to defaults.
|
||||||
|
APP_SETTINGS.CLEAR_SAVED_STATE_HELP,Reset sets & overlay positions,"Tooltip explaining what clearing saved state does. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
APP_SETTINGS.CLICK_FREEZE_TIME_MS,Click freeze time (ms),Slider/numeric input in Settings > Features tab. Sets a time window (in milliseconds) to help with double-click precision.
|
||||||
|
APP_SETTINGS.CLICK_FREEZE_TIME_MS_HELP,Helps with double-click precision,Tooltip for the click freeze time setting.
|
||||||
|
APP_SETTINGS.CLOCK_12H,12-hour clock,Checkbox label in Settings > Look & Feel tab. Toggles between 12-hour and 24-hour time display.
|
||||||
|
APP_SETTINGS.CONTROLS,Controls,Category header in Settings. Groups input/controller-related settings.
|
||||||
|
APP_SETTINGS.DELETE_ALL_CONFIGS,Wipe configuration,Button label in Settings > Troubleshooting tab. Removes all configuration files from conf.d.
|
||||||
|
APP_SETTINGS.DELETE_ALL_CONFIGS_HELP,Remove all configuration files from conf.d,Tooltip explaining the Wipe configuration button.
|
||||||
|
APP_SETTINGS.DOUBLE_CURSOR_FIX,Double cursor fix,Checkbox label in Settings > Miscellaneous tab. Enables a workaround for systems that show two cursors.
|
||||||
|
APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP,Enable this if you see 2 cursors,Tooltip for the double cursor fix checkbox.
|
||||||
|
APP_SETTINGS.DEFAULT_OVERLAY_SCALE,Default overlay size,Slider label in Settings > Look & Feel tab. Sets the default scale for newly created overlays.
|
||||||
|
APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP,Spawn new overlays at this scale.,"Tooltip for the default overlay size slider. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
APP_SETTINGS.DEFAULT_CURVATURE,Default overlay curvature,"Slider label in Settings > Look & Feel tab. Sets the default curvature for new overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
APP_SETTINGS.DEFAULT_OPACITY,Default overlay opacity,"Slider label in Settings > Look & Feel tab. Sets the default opacity for new overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
APP_SETTINGS.DEFAULT_POSITIONING,Default overlay positioning,"Dropdown label in Settings > Look & Feel tab. Sets the default positioning mode (anchored/floating/static) for new overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
APP_SETTINGS.OVERLAY_DEFAULTS_HELP,Only applies to new overlays,"Tooltip shared by default overlay settings (curvature, opacity, positioning). Notes these don't affect existing overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
APP_SETTINGS.ENABLED,Enabled,Label used for enabling space gravity and related physics features in the space drag settings.
|
||||||
|
APP_SETTINGS.FEATURES,Features,Category header in Settings. Previously translated as ${DEFINITIONS.FEATURES}
|
||||||
|
APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE,Mouse move on trigger touch,"Setting in Settings > Features tab. When enabled, moving the trigger touch moves the mouse cursor."
|
||||||
|
APP_SETTINGS.HANDSFREE_POINTER,Handsfree mode,Dropdown label in Settings > Features tab. Selects the input method used when motion controllers are unavailable.
|
||||||
|
APP_SETTINGS.HANDSFREE_POINTER_HELP,"Input to use when motion
|
||||||
|
controllers are unavailable.
|
||||||
|
Left pinch is grab, right is click.",Tooltip for the handsfree mode dropdown.
|
||||||
|
APP_SETTINGS.HANDSFREE_ALT_TAB,App switcher aim,Dropdown/setting in Settings > Features tab. Controls how the alt-tab app switcher is aimed.
|
||||||
|
APP_SETTINGS.HANDSFREE_ALT_TAB_HELP,"Hold Super+X, aim at the desired window, then release to switch focus.",Tooltip explaining the handsfree alt-tab behavior.
|
||||||
|
APP_SETTINGS.HIDE_GRAB_HELP,Hide grab help,Checkbox label in Settings > Look & Feel tab. Hides the grab help overlay/text.
|
||||||
|
APP_SETTINGS.HIDE_USERNAME,Hide username,Checkbox label in Settings > Look & Feel tab. Hides the user's username from the UI.
|
||||||
|
APP_SETTINGS.INPUT_EMULATION_METHOD,Input emulation method,"Dropdown label in Settings > Miscellaneous tab. Selects how WayVR emulates mouse/keyboard input (uinput, Wayland virtual, none)."
|
||||||
|
APP_SETTINGS.INPUT_EMULATION_METHOD_HELP,"Try change this in case mouse or
|
||||||
|
keyboard input does not register.",Tooltip for the input emulation method dropdown.
|
||||||
|
APP_SETTINGS.INPUT_CAPTURE_METHOD,Input capture method,Dropdown label in Settings > Miscellaneous tab. Selects how physical input devices are captured for use inside WayVR.
|
||||||
|
APP_SETTINGS.INPUT_CAPTURE_METHOD_HELP,"Allows using physical peripherial inside WayVR.
|
||||||
|
Super+Z: Switch input between WayVR and real desktop
|
||||||
|
Super+X: Switch between WayVR apps",Tooltip explaining the input capture method setting.
|
||||||
|
APP_SETTINGS.INPUT_PROFILES,Change Input Bindings,Button label in Settings > Controls tab. Opens the controller bindings editor popup.
|
||||||
|
APP_SETTINGS.INPUT_PROFILES_HELP,OpenXR controller input bindings,Tooltip for the Change Input Bindings button.
|
||||||
|
APP_SETTINGS.INVERT_SCROLL_DIRECTION_X,Invert horizontal scroll direction,Checkbox label in Settings > Features tab. Inverts the horizontal scroll direction.
|
||||||
|
APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y,Invert vertical scroll direction,Checkbox label in Settings > Features tab. Inverts the vertical scroll direction.
|
||||||
|
APP_SETTINGS.KEYBOARD_MIDDLE_CLICK,Keyboard middle click,Dropdown label in Settings > Features tab. Selects the modifier key used for middle-click when typing with the laser pointer.
|
||||||
|
APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP,"Modifier to use when typing
|
||||||
|
with purple laser",Tooltip for the keyboard middle-click setting.
|
||||||
|
APP_SETTINGS.KEYBOARD_SOUND_ENABLED,Keyboard sounds,Checkbox label in Settings > Features tab. Enables or disables typing sounds when using the on-screen keyboard.
|
||||||
|
APP_SETTINGS.LANGUAGE,Language,Dropdown label in Settings > Look & Feel tab. Selects the UI language.
|
||||||
|
APP_SETTINGS.LEFT_HANDED_MOUSE,Left-handed mouse,Checkbox label in Settings > Features tab. Swaps mouse buttons for left-handed users.
|
||||||
|
APP_SETTINGS.LEFT_HANDED_MOUSE_HELP,Use this if mouse buttons are swapped,Tooltip for the left-handed mouse checkbox.
|
||||||
|
APP_SETTINGS.LONG_PRESS_DURATION,Long press duration,Setting in Settings > Features tab. Controls how long a press must be held to register as a long press.
|
||||||
|
APP_SETTINGS.LOOK_AND_FEEL,Look & Feel,"Category header in Settings. Groups visual/customization settings like language, opacity, animation speed, color palettes."
|
||||||
|
APP_SETTINGS.MISC,Miscellaneous,"Category header in Settings. Groups troubleshooting and system-level settings like capture method, input emulation, xwayland."
|
||||||
|
APP_SETTINGS.NOTIFICATIONS_ENABLED,Enable notifications,Checkbox label in Settings > Features tab. Enables or disables system notifications within WayVR.
|
||||||
|
APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED,Notification sounds,Checkbox label in Settings > Features tab. Enables or disables sound effects for notifications.
|
||||||
|
APP_SETTINGS.NOT_SUPPORTED,Not supported,Label shown in the space drag/physics settings when a feature (like gravity) is not supported by the current backend.
|
||||||
|
APP_SETTINGS.NO_SKYMAPS_FOUND,No skymaps found,"Label shown in the skymap browser when no skymaps are available locally. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.OPAQUE_BACKGROUND,Opaque background,Checkbox label in Settings > Look & Feel tab. Makes overlay backgrounds fully opaque (no transparency).
|
||||||
|
APP_SETTINGS.OPTION.ANCHORED_HELP,Moves with center marker. Recommended.,Tooltip for the Anchored positioning option.
|
||||||
|
APP_SETTINGS.OPTION.FLOATING_HELP,"Moves independently, recenters.
|
||||||
|
Easy to misplace; not recommended.",Tooltip for the Floating positioning option.
|
||||||
|
APP_SETTINGS.OPTION.STATIC_HELP,Stays in place relative to world.,Tooltip for the Static positioning option.
|
||||||
|
APP_SETTINGS.OPTION.AUTO,Automatic,"Dropdown option for screen capture method. Uses ScreenCopy GPU if supported, otherwise PipeWire GPU."
|
||||||
|
APP_SETTINGS.OPTION.AUTO_HELP,"ScreenCopy GPU if supported,
|
||||||
|
otherwise PipeWire GPU.",Tooltip for the Automatic capture method option.
|
||||||
|
APP_SETTINGS.OPTION.EYE_ONLY,Eye laser,Dropdown option for handsfree pointer mode. Uses only eye-tracking laser (no pinch).
|
||||||
|
APP_SETTINGS.OPTION.EYE_PINCH,Eye + pinch,Dropdown option for handsfree pointer mode. Uses eye-tracking for aiming and pinch for click.
|
||||||
|
APP_SETTINGS.OPTION.HMD_ONLY,HMD laser,Dropdown option for handsfree pointer/alt-tab mode. Uses only the HMD forward laser.
|
||||||
|
APP_SETTINGS.OPTION.HMD_PINCH,HMD + pinch,Dropdown option for handsfree pointer mode. Uses HMD laser for aiming and pinch for click.
|
||||||
|
APP_SETTINGS.OPTION.NONE,None,"Dropdown option used as the no binding or disabled choice in various settings (input emulation, input capture, handsfree pointer, alt modifier, whisper model)."
|
||||||
|
APP_SETTINGS.OPTION.NONE_INPUT_HELP,"Do not emulate mouse and keyboard.
|
||||||
|
Will not be able to interact with screens.",Tooltip for the None input emulation option.
|
||||||
|
APP_SETTINGS.OPTION.NONE_INPUT_CAPTURE_HELP,"Do not capture mouse and keyboard.
|
||||||
|
Will not be able to use physical mouse or
|
||||||
|
keyboard in apps launched inside WayVR.",Tooltip for the None input capture option.
|
||||||
|
APP_SETTINGS.OPTION.PIPEWIRE_HELP,"Fast GPU capture,
|
||||||
|
standard on all desktops.",Tooltip for the PipeWire GPU capture method option.
|
||||||
|
APP_SETTINGS.OPTION.PW_FALLBACK_HELP,"Slow method with high CPU usage.
|
||||||
|
Try in case PipeWire GPU doesn't work",Tooltip for the PipeWire CPU (fallback) capture method option.
|
||||||
|
APP_SETTINGS.OPTION.SCREENCOPY_GPU_HELP,"Fast, no screen share popups.
|
||||||
|
Works on: Hyprland, Niri, River, Sway",Tooltip for the ScreenCopy GPU capture method option.
|
||||||
|
APP_SETTINGS.OPTION.SCREENCOPY_HELP,"Slow, no screen share popups.
|
||||||
|
Works on: Hyprland, Niri, River, Sway",Tooltip for the ScreenCopy CPU capture method option.
|
||||||
|
APP_SETTINGS.OPTION.UINPUT,Device emulation,Dropdown option for input emulation method. Uses the uinput kernel module to emulate input devices.
|
||||||
|
APP_SETTINGS.OPTION.UINPUT_HELP,"Uses the uinput module to emulate a device.
|
||||||
|
Known to work well on most desktops.",Tooltip for the Device emulation (uinput) option.
|
||||||
|
APP_SETTINGS.OPTION.EVDEV_HELP,"Grab input devices for exclusive use.
|
||||||
|
Your user must be in the input group.",Tooltip for the evdev input capture method option.
|
||||||
|
APP_SETTINGS.OPTION.WL_VIRTUAL,Wayland virtual input,Dropdown option for input emulation method. Uses Wayland virtual pointer/keyboard protocols.
|
||||||
|
APP_SETTINGS.OPTION.WL_VIRTUAL_HELP,"Send events to the Wayland compositor using
|
||||||
|
zwlr_virtual_pointer and zwp_virtual_keyboard.
|
||||||
|
Only works reliably on some desktops.
|
||||||
|
Does NOT work on KDE, GNOME or COSMIC.",Tooltip for the Wayland virtual input option.
|
||||||
|
APP_SETTINGS.POINTER_ACCELERATION,Mouse acceleration,Checkbox/dropdown in Settings > Features tab. Toggles adaptive mouse acceleration (on) or constant speed (off).
|
||||||
|
APP_SETTINGS.POINTER_ACCELERATION_HELP,"On: Adaptive mouse acceleration
|
||||||
|
Off: Constant speed",Tooltip for the mouse acceleration setting.
|
||||||
|
APP_SETTINGS.POINTER_LERP_FACTOR,Pointer smoothing,Slider in Settings > Features tab. Controls the linear interpolation (smoothing) factor for pointer movement.
|
||||||
|
APP_SETTINGS.POINTER_SPEED,Mouse speed,Slider in Settings > Features tab. Controls the base mouse pointer speed.
|
||||||
|
APP_SETTINGS.REQUIRES_RESTART,Requires restart,Label shown below settings that require a software restart to take effect.
|
||||||
|
APP_SETTINGS.RESET_PLAYSPACE,Reset playspace,"Button in Settings > Space Drag tab. Clears the stage space offset, resetting playspace position. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.RESET_PLAYSPACE_HELP,Clear the stage space offset.,"Tooltip for the Reset playspace button. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SAVE_PLAYSPACE_CENTER,Save playspace center,"Button in Settings > Space Drag tab. Saves the current playspace center as the reset target. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SAVE_PLAYSPACE_CENTER_HELP,Use current playspace for reset playspace binding.,"Tooltip for the Save playspace center button. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.RESET_PLAYSPACE_CENTER,Reset playspace center,"Button in Settings > Space Drag tab. Clears the previously saved playspace center. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.RESET_PLAYSPACE_CENTER_HELP,Clear previously set playspace center.,"Tooltip for the Reset playspace center button. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.RESTART_SOFTWARE,Restart software,Button in Settings > Troubleshooting tab. Restarts the WayVR software to apply settings that require a restart.
|
||||||
|
APP_SETTINGS.RESTART_SOFTWARE_HELP,Apply settings that require a restart,Tooltip for the Restart software button.
|
||||||
|
APP_SETTINGS.ROUND_MULTIPLIER,UI Edge roundness,Slider in Settings > Look & Feel tab. Controls how rounded the corners of UI elements appear (range 0.1-5.0).
|
||||||
|
APP_SETTINGS.SCREEN_RENDER_DOWN,Render screen at lower resolution,Checkbox in Settings > Miscellaneous tab. Renders the captured desktop screen at a lower resolution to improve performance or reduce aliasing.
|
||||||
|
APP_SETTINGS.SCREEN_RENDER_DOWN_HELP,Helps with aliasing on high-res screens,Tooltip for the lower-resolution screen render setting.
|
||||||
|
APP_SETTINGS.SCROLL_SPEED,Scroll speed,Slider in Settings > Features tab. Controls how fast scrolling occurs.
|
||||||
|
APP_SETTINGS.SELECT_VARIANT,Select variant,Label/button in the color palette or variant selection UI. Allows choosing between different theme variants.
|
||||||
|
APP_SETTINGS.SNAP_ANGLE_DEG,Window pitch & roll snap angle,Slider in Settings > Features tab. Sets the angle (in degrees) at which grabbed windows snap on pitch and roll axes.
|
||||||
|
APP_SETTINGS.SNAP_ANGLE_DEG_HELP,Grabbed windows snap to this angle on pitch and roll axis.,Tooltip for the snap angle setting.
|
||||||
|
APP_SETTINGS.ENABLE_WATCH,Enable watch,"Checkbox in Settings > Look & Feel tab. Enables the wrist watch UI element. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
APP_SETTINGS.SETS_ON_WATCH,Sets on watch,"Checkbox in Settings > Look & Feel tab. Shows overlay sets on the wrist watch display. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}"". ""Set"" was previously translated as ""${DEFINITIONS.SET}""."
|
||||||
|
APP_SETTINGS.SHOW_WELCOME_SCREEN,Show welcome screen,Checkbox in Settings > Features tab. Controls whether the welcome/tutorial screen is shown on first launch.
|
||||||
|
APP_SETTINGS.SKYBOX,Skymap,"Category header in Settings > Skymap tab. Groups skymap-related settings. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.SKYMAP_ALREADY_DOWNLOADED,This skymap is already downloaded. Select desired action.,"Message shown in a dialog when attempting to download a skymap that is already present locally. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.SPACE_DRAG,Playspace,"Category header in Settings. Groups playspace drag/physics settings including reset buttons and gravity. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SPACE_DRAG_MULTIPLIER,Space drag multiplier,"Setting in the space drag physics panel. Multiplies the force applied during space drag. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SPACE_DRAG_AFFECTS_WORLD,Leave overlays behind during space move,"Checkbox in Settings > Space Drag tab. When enabled, moving the playspace leaves overlays behind instead of moving them with the set. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}"". ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SPACE_DRAG_UNLOCKED,Allow space drag on all axes,"Checkbox in Settings > Space Drag tab. Unlocks space drag to work on all axes instead of a constrained axis. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_DAMPING,Damping,"Setting in the space gravity physics panel. Artificial drag to slow movement (0.1 = high drag, 1.0 = no drag)."
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP,"Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag",Tooltip for the inertial damping setting.
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH,Fling strength,Setting in the space gravity physics panel. Intensity multiplier for the gravitational launch force after space-drag.
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH_HELP,"Intensity multiplier of gravitational launch force after space-drag.
|
||||||
|
0.0 - no movement at all, 2.0 - double intensity","Tooltip for the fling strength setting. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_GRAVITY,Gravity,Setting in the space gravity physics panel. Amount of downward force (0.0 = no gravity).
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_GRAVITY_HELP,Amount of downwards force. 0.0 - no gravity,Tooltip for the gravity setting.
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION,Ground friction,"Setting in the space gravity physics panel. Friction when touching the ground (0.0 = ice-like, 1.0 = rough)."
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION_HELP,"Amount of friction slowing you down if you're touching the ground.
|
||||||
|
0.0 - no friction (just like on ice), 1.0 - rough surface",Tooltip for the ground friction setting.
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT,Floor height,Setting in the space gravity physics panel. The Y position where the virtual floor is.
|
||||||
|
APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT_HELP,The Y position where the floor is. Gravity stops when you reach this height.,Tooltip for the floor height setting.
|
||||||
|
APP_SETTINGS.SPACE_ROTATE_UNLOCKED,Allow space rotate on all axes,"Checkbox in Settings > Space Drag tab. Unlocks space rotate to work on all axes. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
|
||||||
|
APP_SETTINGS.TROUBLESHOOTING,Troubleshooting,"Category header in Settings. Groups diagnostic/reset actions like clearing tokens, wiping config, and restarting."
|
||||||
|
APP_SETTINGS.UI_GRADIENT_INTENSITY,UI Gradient intensity,Slider in Settings > Look & Feel tab. Controls the intensity of gradient effects on the UI (range 0.0-1.0).
|
||||||
|
APP_SETTINGS.UPRIGHT_SCREEN_FIX,Upright screen fix,Checkbox in Settings > Miscellaneous tab. Fixes upright screen orientation on some desktop environments.
|
||||||
|
APP_SETTINGS.UPRIGHT_SCREEN_FIX_HELP,Fixes upright screens on some desktops,Tooltip for the upright screen fix checkbox.
|
||||||
|
APP_SETTINGS.USE_PASSTHROUGH,Enable passthrough,Checkbox in Settings > Skybox tab. Allows camera passthrough mode if the XR runtime supports it.
|
||||||
|
APP_SETTINGS.USE_PASSTHROUGH_HELP,Allow passthrough if the XR runtime supports it,Tooltip for the passthrough checkbox.
|
||||||
|
APP_SETTINGS.USE_SKYBOX,Show skymap,"Checkbox in Settings > Skybox tab. Shows a skybox when there's no scene app or passthrough active. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.USE_SKYBOX_HELP,Show a skymap if there's no scene app or passthrough,"Tooltip for the enable skybox checkbox. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.WATCH_VIEW_ANGLE,Watch view angles,"Setting in Settings > Look & Feel tab. Controls the view angles at which the wrist watch fades in/out. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
APP_SETTINGS.WATCH_VIEW_ANGLE_HELP,Control how the watch fades away,"Tooltip for the watch view angles setting. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
APP_SETTINGS.WHISPER.NEED_TO_DOWNLOAD_MODEL,"The selected model needs to be downloaded.
|
||||||
|
Download it right now?",Message shown in a dialog box when the user selects a Whisper model that hasn't been downloaded yet.
|
||||||
|
APP_SETTINGS.WHISPER.REMOVE_UNUSED_MODELS,"You are turning off the speech-to-text feature.
|
||||||
|
Would you like to remove downloaded Whisper models to free up space?",Message shown in a dialog box when the user disables the whisper feature.
|
||||||
|
APP_SETTINGS.WHISPER_MODEL,Speech-to-text model,Dropdown label in Settings > Features tab. Selects which Whisper model to use for speech-to-text.
|
||||||
|
APP_SETTINGS.WHISPER_MODEL_HELP,"Whisper model to use.
|
||||||
|
Larger models produce more accurate
|
||||||
|
results, but consume more VRAM.",Tooltip for the speech-to-text model dropdown.
|
||||||
|
APP_SETTINGS.GRID_OPACITY,Floor grid opacity,Slider in Settings > Skybox tab. Controls the opacity of the floor grid when skybox is enabled.
|
||||||
|
APP_SETTINGS.GRID_OPACITY_HELP,Opacity of the floor grid when the skymap is enabled,"Tooltip for the floor grid opacity slider. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
|
||||||
|
APP_SETTINGS.XWAYLAND_BY_DEFAULT,Run apps in Compatibility mode by default,Checkbox in Settings > Miscellaneous tab. Launches apps in Cage/compatibility mode by default.
|
||||||
|
APP_SETTINGS.SAVE,Save,Button label in the controller bindings editor popup. Saves the current bindings configuration.
|
||||||
|
APP_SETTINGS.CANCEL,Cancel,Button label in the controller bindings editor popup and in whisper model dialogs. Cancels/dismisses the dialog without saving.
|
||||||
|
APPLICATION_LAUNCHER,Application launcher,App launcher configuration popup title - appears as the label for the app launch/options dialog.
|
||||||
|
APPLICATION_STARTED,Application started,Toast notification shown after a successful app launch.
|
||||||
|
APPLICATIONS,Applications,Tab label in the dashboard sidebar for the Apps tab.
|
||||||
|
AUDIO.AUTO_SWITCH_TO_VR_AUDIO,Auto-switch to VR audio,Tooltip on the auto-switch audio button in the audio settings popup.
|
||||||
|
AUDIO.CARDS,Cards,Button label in the audio settings popup for selecting audio card profiles.
|
||||||
|
AUDIO.FAILED_TO_SWITCH_MICROPHONE,Failed to switch microphone,Error toast shown when switching to a VR microphone fails.
|
||||||
|
AUDIO.MICROPHONE_SET_SUCCESSFULLY,Microphone set successfully,Toast notification after successfully switching the microphone.
|
||||||
|
AUDIO.MICROPHONES,Microphones,Button label in the audio settings popup for selecting microphone sources.
|
||||||
|
AUDIO.NO_VR_MICROPHONE_SWITCH_MANUALLY,No VR microphone found. Switch it manually.,Toast shown when no VR microphone is detected and manual switching is needed.
|
||||||
|
AUDIO.NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY,No VR speakers found. Switch them manually.,Toast shown when no VR speakers are detected after auto-switch.
|
||||||
|
AUDIO.SELECT_AUDIO_CARD_PROFILE,Select audio card profile,Bold label in the audio settings popup for choosing an audio card profile.
|
||||||
|
AUDIO.SETTINGS,Audio settings,Window title for the audio settings popup opened from the dashboard.
|
||||||
|
AUDIO.SPEAKERS,Speakers,Button label in the audio settings popup for selecting speaker sinks.
|
||||||
|
AUDIO.SPEAKERS_SET_SUCCESSFULLY,Speakers set successfully,Toast notification after successfully switching speakers.
|
||||||
|
AUDIO.VOLUME,Volume,Tooltip on the audio volume button in the dashboard.
|
||||||
|
CLOSE_WINDOW,Close window,"Close button label used in dialog boxes, download file popup, and window options."
|
||||||
|
CREATION_DATE,Creation date,Column label in the remote skymap downloader showing file metadata.
|
||||||
|
DEBUG_INFO,Debug info,Tab name in the Monado runtime section of the dashboard.
|
||||||
|
DISPLAY_BRIGHTNESS,Display brightness,Label for the display brightness setting in the Monado general settings tab.
|
||||||
|
DONATE.SUPPORT_US,Support us,Button tooltip on the home screen donate button.
|
||||||
|
DONATE.DESCRIPTION,"We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.",Description text on the donate tab explaining the project.
|
||||||
|
DONATE.THANK_YOU_WAYVR,Thank you from the WayVR Team!,Thank you message displayed on the donate tab.
|
||||||
|
DONATE.BUTTON_TOOLTIP,Donate via Open Collective,Tooltip on the donate button on the donate tab.
|
||||||
|
DONATE.CURRENT_SUPPORTERS,Current Supporters,Section header on the donate tab listing supporters.
|
||||||
|
DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN,Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it.
|
||||||
|
DONATE.BROUGHT_TO_YOU_VARIANTS_RARE,Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
|
||||||
|
DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE,Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|The savior of our sanity: {USER}|Leading the way: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
|
||||||
|
DOWNLOAD,Download,Button in the Whisper model download dialog to confirm downloading a model.
|
||||||
|
DOWNLOADER,Downloader,Window title for the file download popup.
|
||||||
|
WELCOME.ALL_SET,You're all set!,Main heading on the final welcome/tutorial page.
|
||||||
|
WELCOME.BASICS,These basics will allow you to start using WayVR with ease.,Description text on the final welcome page under the You are all set heading.
|
||||||
|
WELCOME.CENTER_MARKER,Center marker is what will appear in front of you when recentering. Place overlays around it!,"Description of the center marker on the moving your set tutorial page. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
|
||||||
|
WELCOME.DOUBLE_PRESS_TO_TOGGLE,"Double-press B (on Index) or Y (on Meta) to show, recenter or hide your set. Try it now.","Instruction text on the working set tutorial page explaining the double-press gesture. ""Set"" was previously translated as ""${DEFINITIONS.SET}""."
|
||||||
|
WELCOME.FEATURES_DOCUMENTATION,"There are many other features worth customizing. For more information, check the documentation at",Text on the final welcome page linking to documentation.
|
||||||
|
WELCOME.FINISH_TUTORIAL,Finish tutorial,Button text on the final welcome page to complete the tutorial.
|
||||||
|
WELCOME.GRAB_BOTH_HANDS,Grab it with both hands if you want to move a specific overlay in your set.,Instruction text on the moving your set tutorial page for two-hand grab.
|
||||||
|
WELCOME.GRAB_ONE_HAND,Grab it with one hand to move your set.,Instruction text on the moving your set tutorial page for one-hand grab.
|
||||||
|
WELCOME.GREETING,Hi there!,Greeting label on the first welcome page.
|
||||||
|
WELCOME.GUIDE_INTRO,Let us guide you through your first steps.,Intro text on the first welcome page below the greeting.
|
||||||
|
WELCOME.LASER_COLORS,Laser Colors,Page title on the laser colors tutorial page.
|
||||||
|
WELCOME.LASER_FUNCTIONALITY,"Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them!",Description text on the laser colors tutorial page.
|
||||||
|
WELCOME.LAST_PAGE_INFO,This tutorial will stop showing up once you get to the last page.,Info text on the first welcome page noting the tutorial is near the end.
|
||||||
|
WELCOME.LOOK_AT_LEFT_WRIST,Look at your left wrist. That's your watch.,"Instruction text on the watch tutorial page. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER, Middle-click Mode: Purple laser,Laser mode label on the laser colors tutorial page.
|
||||||
|
WELCOME.MOVING_YOUR_SET,Moving your set,Page title on the moving your set tutorial page.
|
||||||
|
WELCOME.NEXT_BUTTON,"Press ""Next"" button below to get started.",Label on the first welcome page pointing to the next button.
|
||||||
|
WELCOME.REGULAR_MODE_BLUE_LASER,Regular Mode: Blue laser,Laser mode label on the laser colors tutorial page.
|
||||||
|
WELCOME.REPOSITION_THIS_WINDOW_BY_GRABBING,Reposition this window using your controller's grip action.,Instruction text on the first welcome page about window repositioning.
|
||||||
|
WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER,Right-click Mode: Orange laser,Laser mode label on the laser colors tutorial page.
|
||||||
|
WELCOME.THANKS_FOR_INSTALLING,Thank you for installing WayVR!,Thanks text on the first welcome page below the greeting.
|
||||||
|
WELCOME.WATCH,Watch,"Page title on the watch/tutorial page. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
|
||||||
|
WELCOME.WORKING_SET,Working Set,"Page title on the working set tutorial page. ""Set"" was previously translated as ""${DEFINITIONS.SET}"". Working as in ""Current""."
|
||||||
|
DOWNLOAD_AGAIN,Download again,Button in the skymap already downloaded dialog to re-download a skymap.
|
||||||
|
DOWNLOADING_FILE,Downloading file...,Status label in the download file popup showing download progress.
|
||||||
|
FAILED_TO_LAUNCH_APPLICATION,Failed to launch a application:,Error prefix in the toast shown when app launch fails.
|
||||||
|
GAME_LAUNCHED,Game launched,Toast notification shown after successfully launching a game via Steam.
|
||||||
|
GAME_LIST.NO_GAMES_FOUND,No games found,Empty state text shown in the game list when no games are installed.
|
||||||
|
GAME_LIST.RUNNING_GAMES_LIST,List of running games,Section label in the running games list view.
|
||||||
|
GAMES,Games,Tab label in the dashboard sidebar for the Games tab.
|
||||||
|
GENERAL_SETTINGS,General settings,Tab name and group box title in the Monado runtime settings.
|
||||||
|
GETTING_STARTED,Getting started,Tab label in the dashboard sidebar for the Welcome/tutorial tab.
|
||||||
|
HEIGHT,Height,Label for the height dimension field in the add display popup.
|
||||||
|
HELLO,Hello!,Fallback greeting on the home screen when username is hidden.
|
||||||
|
HELLO_USER,"Hello, {USER}!",Greeting on the home screen with the user name substituted in.
|
||||||
|
HIDE,Hide,Used in the double-press tutorial context for hiding the set.
|
||||||
|
HOME_SCREEN,Home,Tab label in the dashboard sidebar for the Home tab.
|
||||||
|
MODIFICATION_DATE,Modification date,Column label in the remote skymap downloader showing file metadata.
|
||||||
|
MONADO_RUNTIME,Monado runtime,Tab label in the dashboard sidebar for the Monado runtime tab.
|
||||||
|
LOADING,Loading...,Label in the loading spinner template used across the UI.
|
||||||
|
POPUP_ADD_DISPLAY.RESOLUTION,Resolution,Label for the resolution field in the add display popup.
|
||||||
|
PROCESS.FORCE_KILL,Force-kill,Tooltip on the kill button in the running games list.
|
||||||
|
PROCESS.STOP,Stop,Tooltip on the stop button in the running games list.
|
||||||
|
PROCESS_LIST,Process list,Tab name and group box title in the Monado runtime process list section.
|
||||||
|
REFRESH,Refresh,Tooltip on the refresh button in the running games list.
|
||||||
|
REMOVE,Remove,Button label in the skymap already downloaded dialog and Whisper cleanup dialog to remove files.
|
||||||
|
APPLY,Apply,Button label in the skymap already downloaded dialog to apply the selected skymap.
|
||||||
|
RELOAD_FROM_DISK,Reload from disk,Tooltip on the reload button in the skymap list view.
|
||||||
|
SETTINGS,Settings,Tab label in the dashboard sidebar for the Settings tab. Previously translated as ${DEFINITIONS.SETT}
|
||||||
|
SHOW,Show,Used in the double-press tutorial context for showing the set.
|
||||||
|
TARGET_PATH,Target path,Label for the target path display in the download file popup.
|
||||||
|
TERMINATE_PROCESS,Terminate process,Button label in the window options bar to kill a process.
|
||||||
|
VERSION,Version,Label for the version display in the remote skymap downloader.
|
||||||
|
WIDTH,Width,Label for the width dimension field in the add display popup.
|
||||||
|
PINNED_APPS,Pinned applications,"Section header label for the pinned apps list on the Apps tab, a.k.a. ""Favourites"""
|
||||||
|
SAVED_TO_FAVOURITES,Saved to pinned apps,"Toast notification shown after pinning an app to favourites. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
|
||||||
|
ADD_TO_FAVOURITES,Add to pinned apps,"Label on the pin button in the app launcher popup that is used to add to favourites.. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
|
||||||
|
ADD_TO_FAVOURITES_HINT,Save preset and pin it to the app drawer,"Tooltip on the add to favourites button in the app launcher popup. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
|
||||||
|
REMOVE_FROM_FAVOURITES,Remove from pinned apps,"Label on the unpin section in the app launcher popup. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
|
||||||
|
EMPTY,Empty,Label shown in the pinned apps section when there are no pinned apps.
|
||||||
|
|
|
@ -1,4 +1,21 @@
|
||||||
{
|
{
|
||||||
|
"DEFINITIONS": {
|
||||||
|
"ANCHORED": "Anchored",
|
||||||
|
"FLOATING": "Floating",
|
||||||
|
"STATIC": "Static",
|
||||||
|
"SET": "Set",
|
||||||
|
"WATCH": "Watch",
|
||||||
|
"DASHBOARD": "Dashboard",
|
||||||
|
"EDIT_MODE": "Edit Mode",
|
||||||
|
"SETTINGS": "Settings",
|
||||||
|
"KEYBOARD": "Keyboard",
|
||||||
|
"TASKBAR": "Taskbar",
|
||||||
|
"FEATURES": "Features",
|
||||||
|
"OVERLAY": "Overlay",
|
||||||
|
"SKYMAP": "Skymap",
|
||||||
|
"PLAYSPACE": "Playspace",
|
||||||
|
"D_PAD": "D-pad"
|
||||||
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"RECENTER_PLAYSPACE": "Re-center playspace"
|
"RECENTER_PLAYSPACE": "Re-center playspace"
|
||||||
},
|
},
|
||||||
|
|
@ -17,15 +34,6 @@
|
||||||
"CAGE": "Compatibility mode (Cage)",
|
"CAGE": "Compatibility mode (Cage)",
|
||||||
"NATIVE": "Native mode"
|
"NATIVE": "Native mode"
|
||||||
},
|
},
|
||||||
"POS": {
|
|
||||||
"ANCHORED": "Anchored",
|
|
||||||
"ANCHORED_HELP": "Stays in place relative to center marker.",
|
|
||||||
"FLOATING": "Floating",
|
|
||||||
"FLOATING_HELP": "Moves independently, recenters on show.",
|
|
||||||
"STATIC": "Static",
|
|
||||||
"STATIC_HELP": "Not part of any set. Does not recenter."
|
|
||||||
},
|
|
||||||
"POS_TITLE": "Positioning",
|
|
||||||
"RES_TITLE": "Resolution"
|
"RES_TITLE": "Resolution"
|
||||||
},
|
},
|
||||||
"APP_SETTINGS": {
|
"APP_SETTINGS": {
|
||||||
|
|
@ -93,9 +101,16 @@
|
||||||
},
|
},
|
||||||
"BROWSE_ONLINE_CATALOG": "Browse online catalog...",
|
"BROWSE_ONLINE_CATALOG": "Browse online catalog...",
|
||||||
"BROWSE_SKYMAPS": "Browse skymaps",
|
"BROWSE_SKYMAPS": "Browse skymaps",
|
||||||
"CAPTURE_METHOD": "Wayland screen capture",
|
"CAPTURE_METHOD": "Screen capture method",
|
||||||
"CAPTURE_METHOD_HELP": "Try changing this if you are\nexperiencing black or glitchy screens",
|
"CAPTURE_METHOD_HELP": "Try changing this if you are\nexperiencing black or glitchy screens",
|
||||||
"COLOR_KEYING": "Color keying",
|
"COLOR_KEYING": "Color keying",
|
||||||
|
"COLOR_PALETTE": "Color palette",
|
||||||
|
"COLOR_PALETTE_HELP": "Click to browse color palettes.\nTo create custom ones, see website!",
|
||||||
|
"COLOR_PALETTES": "Color palettes",
|
||||||
|
"COLOR_PALETTE_CURRENT": "Currently active theme.",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Add your own custom theme!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Click to open web manual.",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "Click to use this theme.",
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens",
|
"CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens",
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "Prompt for screen selection on next start",
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "Prompt for screen selection on next start",
|
||||||
"CLEAR_SAVED_STATE": "Clear saved state",
|
"CLEAR_SAVED_STATE": "Clear saved state",
|
||||||
|
|
@ -110,15 +125,23 @@
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors",
|
"DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors",
|
||||||
"DEFAULT_OVERLAY_SCALE": "Default overlay size",
|
"DEFAULT_OVERLAY_SCALE": "Default overlay size",
|
||||||
"DEFAULT_OVERLAY_SCALE_HELP": "Spawn new overlays at this scale.",
|
"DEFAULT_OVERLAY_SCALE_HELP": "Spawn new overlays at this scale.",
|
||||||
|
"DEFAULT_CURVATURE": "Default overlay curvature",
|
||||||
|
"DEFAULT_OPACITY": "Default overlay opacity",
|
||||||
|
"DEFAULT_POSITIONING": "Default overlay positioning",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "Only applies to new overlays",
|
||||||
"ENABLED": "Enabled",
|
"ENABLED": "Enabled",
|
||||||
"FEATURES": "Features",
|
"FEATURES": "Features",
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "Mouse move on trigger touch",
|
"FOCUS_FOLLOWS_MOUSE_MODE": "Mouse move on trigger touch",
|
||||||
"HANDSFREE_POINTER": "Handsfree mode",
|
"HANDSFREE_POINTER": "Handsfree mode",
|
||||||
"HANDSFREE_POINTER_HELP": "Input to use when motion\ncontrollers are unavailable.\nLeft pinch is grab, right is click.",
|
"HANDSFREE_POINTER_HELP": "Input to use when motion\ncontrollers are unavailable.\nLeft pinch is grab, right is click.",
|
||||||
|
"HANDSFREE_ALT_TAB": "App switcher aim",
|
||||||
|
"HANDSFREE_ALT_TAB_HELP": "Hold Super+X, aim at the desired window, then release to switch focus.",
|
||||||
"HIDE_GRAB_HELP": "Hide grab help",
|
"HIDE_GRAB_HELP": "Hide grab help",
|
||||||
"HIDE_USERNAME": "Hide username",
|
"HIDE_USERNAME": "Hide username",
|
||||||
"INPUT_EMULATION_METHOD": "Input emulation method",
|
"INPUT_EMULATION_METHOD": "Input emulation method",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "Try change this in case mouse or\nkeyboard input does not register.",
|
"INPUT_EMULATION_METHOD_HELP": "Try change this in case mouse or\nkeyboard input does not register.",
|
||||||
|
"INPUT_CAPTURE_METHOD": "Input capture method",
|
||||||
|
"INPUT_CAPTURE_METHOD_HELP": "Allows using physical peripherial inside WayVR.\n Super+Z: Switch input between WayVR and real desktop\n Super+X: Switch between WayVR apps",
|
||||||
"INPUT_PROFILES": "Change Input Bindings",
|
"INPUT_PROFILES": "Change Input Bindings",
|
||||||
"INPUT_PROFILES_HELP": "OpenXR controller input bindings",
|
"INPUT_PROFILES_HELP": "OpenXR controller input bindings",
|
||||||
"INVERT_SCROLL_DIRECTION_X": "Invert horizontal scroll direction",
|
"INVERT_SCROLL_DIRECTION_X": "Invert horizontal scroll direction",
|
||||||
|
|
@ -138,27 +161,39 @@
|
||||||
"NO_SKYMAPS_FOUND": "No skymaps found",
|
"NO_SKYMAPS_FOUND": "No skymaps found",
|
||||||
"OPAQUE_BACKGROUND": "Opaque background",
|
"OPAQUE_BACKGROUND": "Opaque background",
|
||||||
"OPTION": {
|
"OPTION": {
|
||||||
|
"ANCHORED_HELP": "Moves with center marker. Recommended.",
|
||||||
|
"FLOATING_HELP": "Moves independently, recenters.\nEasy to misplace; not recommended.",
|
||||||
|
"STATIC_HELP": "Stays in place relative to world.",
|
||||||
"AUTO": "Automatic",
|
"AUTO": "Automatic",
|
||||||
"AUTO_HELP": "ScreenCopy GPU if supported,\notherwise PipeWire GPU.",
|
"AUTO_HELP": "ScreenCopy GPU if supported,\notherwise PipeWire GPU.",
|
||||||
"EYE_ONLY": "Eye only",
|
"EYE_ONLY": "Eye laser",
|
||||||
"EYE_PINCH": "Eye + pinch",
|
"EYE_PINCH": "Eye + pinch",
|
||||||
"HMD_ONLY": "HMD only",
|
"HMD_ONLY": "HMD laser",
|
||||||
"HMD_PINCH": "HMD + pinch",
|
"HMD_PINCH": "HMD + pinch",
|
||||||
"NONE": "None",
|
"NONE": "None",
|
||||||
"NONE_INPUT_HELP": "Do not emulate mouse and keyboard.\nWill not be able to interact with screens.",
|
"NONE_INPUT_HELP": "Do not emulate mouse and keyboard.\nWill not be able to interact with screens.",
|
||||||
|
"NONE_INPUT_CAPTURE_HELP": "Do not capture mouse and keyboard.\nWill not be able to use physical mouse or\nkeyboard in apps launched inside WayVR.",
|
||||||
"PIPEWIRE_HELP": "Fast GPU capture,\nstandard on all desktops.",
|
"PIPEWIRE_HELP": "Fast GPU capture,\nstandard on all desktops.",
|
||||||
"PW_FALLBACK_HELP": "Slow method with high CPU usage.\nTry in case PipeWire GPU doesn't work",
|
"PW_FALLBACK_HELP": "Slow method with high CPU usage.\nTry in case PipeWire GPU doesn't work",
|
||||||
"SCREENCOPY_GPU_HELP": "Fast, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
|
"SCREENCOPY_GPU_HELP": "Fast, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
|
||||||
"SCREENCOPY_HELP": "Slow, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
|
"SCREENCOPY_HELP": "Slow, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
|
||||||
"UINPUT": "Device emulation",
|
"UINPUT": "Device emulation",
|
||||||
"UINPUT_HELP": "Uses the uinput module to emulate a device.\nYour user must be in the input group.\nKnown to work well on most desktops.",
|
"UINPUT_HELP": "Uses the uinput module to emulate a device.\nKnown to work well on most desktops.",
|
||||||
|
"EVDEV_HELP": "Grab input devices for exclusive use.\nYour user must be in the input group.",
|
||||||
"WL_VIRTUAL": "Wayland virtual input",
|
"WL_VIRTUAL": "Wayland virtual input",
|
||||||
"WL_VIRTUAL_HELP": "Send events to the Wayland compositor using\nzwlr_virtual_pointer and zwp_virtual_keyboard.\nOnly works reliably on some desktops.\nDoes NOT work on KDE, GNOME or COSMIC."
|
"WL_VIRTUAL_HELP": "Send events to the Wayland compositor using\nzwlr_virtual_pointer and zwp_virtual_keyboard.\nOnly works reliably on some desktops.\nDoes NOT work on KDE, GNOME or COSMIC."
|
||||||
},
|
},
|
||||||
|
"POINTER_ACCELERATION": "Mouse acceleration",
|
||||||
|
"POINTER_ACCELERATION_HELP": "On: Adaptive mouse acceleration\nOff: Constant speed",
|
||||||
"POINTER_LERP_FACTOR": "Pointer smoothing",
|
"POINTER_LERP_FACTOR": "Pointer smoothing",
|
||||||
|
"POINTER_SPEED": "Mouse speed",
|
||||||
"REQUIRES_RESTART": "Requires restart",
|
"REQUIRES_RESTART": "Requires restart",
|
||||||
"RESET_PLAYSPACE": "Reset playspace",
|
"RESET_PLAYSPACE": "Reset playspace",
|
||||||
"RESET_PLAYSPACE_HELP": "Clear the stage space offset.",
|
"RESET_PLAYSPACE_HELP": "Clear the stage space offset.",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "Save playspace center",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "Use current playspace for reset playspace binding.",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "Reset playspace center",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "Clear previously set playspace center.",
|
||||||
"RESTART_SOFTWARE": "Restart software",
|
"RESTART_SOFTWARE": "Restart software",
|
||||||
"RESTART_SOFTWARE_HELP": "Apply settings that require a restart",
|
"RESTART_SOFTWARE_HELP": "Apply settings that require a restart",
|
||||||
"ROUND_MULTIPLIER": "UI Edge roundness",
|
"ROUND_MULTIPLIER": "UI Edge roundness",
|
||||||
|
|
@ -166,13 +201,16 @@
|
||||||
"SCREEN_RENDER_DOWN_HELP": "Helps with aliasing on high-res screens",
|
"SCREEN_RENDER_DOWN_HELP": "Helps with aliasing on high-res screens",
|
||||||
"SCROLL_SPEED": "Scroll speed",
|
"SCROLL_SPEED": "Scroll speed",
|
||||||
"SELECT_VARIANT": "Select variant",
|
"SELECT_VARIANT": "Select variant",
|
||||||
|
"SNAP_ANGLE_DEG": "Window pitch & roll snap angle",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "Grabbed windows snap to this angle on pitch and roll axis.",
|
||||||
"ENABLE_WATCH": "Enable watch",
|
"ENABLE_WATCH": "Enable watch",
|
||||||
"SETS_ON_WATCH": "Sets on watch",
|
"SETS_ON_WATCH": "Sets on watch",
|
||||||
"SHOW_WELCOME_SCREEN": "Show welcome screen",
|
"SHOW_WELCOME_SCREEN": "Show welcome screen",
|
||||||
"SKYBOX": "Skybox",
|
"SKYBOX": "Skymap",
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
|
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
|
||||||
"SPACE_DRAG": "Space drag",
|
"SPACE_DRAG": "Playspace",
|
||||||
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
|
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "Leave overlays behind during space move",
|
||||||
"SPACE_DRAG_UNLOCKED": "Allow space drag on all axes",
|
"SPACE_DRAG_UNLOCKED": "Allow space drag on all axes",
|
||||||
"SPACE_GRAVITY_DAMPING": "Damping",
|
"SPACE_GRAVITY_DAMPING": "Damping",
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag",
|
"SPACE_GRAVITY_DAMPING_HELP": "Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag",
|
||||||
|
|
@ -191,8 +229,8 @@
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Fixes upright screens on some desktops",
|
"UPRIGHT_SCREEN_FIX_HELP": "Fixes upright screens on some desktops",
|
||||||
"USE_PASSTHROUGH": "Enable passthrough",
|
"USE_PASSTHROUGH": "Enable passthrough",
|
||||||
"USE_PASSTHROUGH_HELP": "Allow passthrough if the XR runtime supports it",
|
"USE_PASSTHROUGH_HELP": "Allow passthrough if the XR runtime supports it",
|
||||||
"USE_SKYBOX": "Enable skybox",
|
"USE_SKYBOX": "Show skymap",
|
||||||
"USE_SKYBOX_HELP": "Show a skybox if there's no scene app or passthrough",
|
"USE_SKYBOX_HELP": "Show a skymap if there's no scene app or passthrough",
|
||||||
"WATCH_VIEW_ANGLE": "Watch view angles",
|
"WATCH_VIEW_ANGLE": "Watch view angles",
|
||||||
"WATCH_VIEW_ANGLE_HELP": "Control how the watch fades away",
|
"WATCH_VIEW_ANGLE_HELP": "Control how the watch fades away",
|
||||||
"WHISPER": {
|
"WHISPER": {
|
||||||
|
|
@ -202,7 +240,7 @@
|
||||||
"WHISPER_MODEL": "Speech-to-text model",
|
"WHISPER_MODEL": "Speech-to-text model",
|
||||||
"WHISPER_MODEL_HELP": "Whisper model to use.\nLarger models produce more accurate\nresults, but consume more VRAM.",
|
"WHISPER_MODEL_HELP": "Whisper model to use.\nLarger models produce more accurate\nresults, but consume more VRAM.",
|
||||||
"GRID_OPACITY": "Floor grid opacity",
|
"GRID_OPACITY": "Floor grid opacity",
|
||||||
"GRID_OPACITY_HELP": "Opacity of the floor grid when the skybox is enabled",
|
"GRID_OPACITY_HELP": "Opacity of the floor grid when the skymap is enabled",
|
||||||
"XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default",
|
"XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default",
|
||||||
"SAVE": "Save",
|
"SAVE": "Save",
|
||||||
"CANCEL": "Cancel"
|
"CANCEL": "Cancel"
|
||||||
|
|
@ -233,15 +271,18 @@
|
||||||
"DESCRIPTION": "We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.",
|
"DESCRIPTION": "We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.",
|
||||||
"THANK_YOU_WAYVR": "Thank you from the WayVR Team!",
|
"THANK_YOU_WAYVR": "Thank you from the WayVR Team!",
|
||||||
"BUTTON_TOOLTIP": "Donate via Open Collective",
|
"BUTTON_TOOLTIP": "Donate via Open Collective",
|
||||||
"CURRENT_SUPPORTERS": "Current Supporters"
|
"CURRENT_SUPPORTERS": "Current Supporters",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|Leading the way: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER}"
|
||||||
},
|
},
|
||||||
"DOWNLOAD": "Download",
|
"DOWNLOAD": "Download",
|
||||||
"DOWNLOADER": "Downloader",
|
"DOWNLOADER": "Downloader",
|
||||||
"WELCOME": {
|
"WELCOME": {
|
||||||
"ALL_SET": "You're all set!",
|
"ALL_SET": "You're all set!",
|
||||||
"BASICS": "These basics will allow you to start using WayVR with ease.",
|
"BASICS": "These basics will allow you to start using WayVR with ease.",
|
||||||
"CENTER_MARKER": "Center marker determines the center or your set.",
|
"CENTER_MARKER": "Center marker is what will appear in front of you when recentering. Place overlays around it!",
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "Double-press B (on Index) or Y (on Meta) to toggle the visibility of your workspace. Try it now.",
|
"DOUBLE_PRESS_TO_TOGGLE": "Double-press B (on Index) or Y (on Meta) to show, recenter or hide your set. Try it now.",
|
||||||
"FEATURES_DOCUMENTATION": "There are many other features worth customizing. For more information, check the documentation at",
|
"FEATURES_DOCUMENTATION": "There are many other features worth customizing. For more information, check the documentation at",
|
||||||
"FINISH_TUTORIAL": "Finish tutorial",
|
"FINISH_TUTORIAL": "Finish tutorial",
|
||||||
"GRAB_BOTH_HANDS": "Grab it with both hands if you want to move a specific overlay in your set.",
|
"GRAB_BOTH_HANDS": "Grab it with both hands if you want to move a specific overlay in your set.",
|
||||||
|
|
@ -252,12 +293,12 @@
|
||||||
"LASER_FUNCTIONALITY": "Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them!",
|
"LASER_FUNCTIONALITY": "Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them!",
|
||||||
"LAST_PAGE_INFO": "This tutorial will stop showing up once you get to the last page.",
|
"LAST_PAGE_INFO": "This tutorial will stop showing up once you get to the last page.",
|
||||||
"LOOK_AT_LEFT_WRIST": "Look at your left wrist. That's your watch.",
|
"LOOK_AT_LEFT_WRIST": "Look at your left wrist. That's your watch.",
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Middle-click Mode: Purple laser",
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Middle-click Mode: Purple laser",
|
||||||
"MOVING_YOUR_SET": "Moving your set",
|
"MOVING_YOUR_SET": "Moving your set",
|
||||||
"NEXT_BUTTON": "Press \"Next\" button below to get started.",
|
"NEXT_BUTTON": "Press Next button below to get started.",
|
||||||
"REGULAR_MODE_BLUE_LASER": "— Regular Mode: Blue laser",
|
"REGULAR_MODE_BLUE_LASER": "Regular Mode: Blue laser",
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposition this window using your controller's grip action.",
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposition this window using your controller's grip action.",
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Right-click Mode: Orange laser",
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "Right-click Mode: Orange laser",
|
||||||
"THANKS_FOR_INSTALLING": "Thank you for installing WayVR!",
|
"THANKS_FOR_INSTALLING": "Thank you for installing WayVR!",
|
||||||
"WATCH": "Watch",
|
"WATCH": "Watch",
|
||||||
"WORKING_SET": "Working Set"
|
"WORKING_SET": "Working Set"
|
||||||
|
|
@ -298,5 +339,11 @@
|
||||||
"TARGET_PATH": "Target path",
|
"TARGET_PATH": "Target path",
|
||||||
"TERMINATE_PROCESS": "Terminate process",
|
"TERMINATE_PROCESS": "Terminate process",
|
||||||
"VERSION": "Version",
|
"VERSION": "Version",
|
||||||
"WIDTH": "Width"
|
"WIDTH": "Width",
|
||||||
|
"PINNED_APPS": "Pinned applications",
|
||||||
|
"SAVED_TO_FAVOURITES": "Saved to pinned apps",
|
||||||
|
"ADD_TO_FAVOURITES": "Add to pinned apps",
|
||||||
|
"ADD_TO_FAVOURITES_HINT": "Save preset and pin it to the app drawer",
|
||||||
|
"REMOVE_FROM_FAVOURITES": "Remove from pinned apps",
|
||||||
|
"EMPTY": "Empty"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,114 +1,56 @@
|
||||||
{
|
{
|
||||||
"HOME_SCREEN": "Inicio",
|
"DEFINITIONS": {
|
||||||
"MONADO_RUNTIME": "Monado tiempo de ejecución",
|
"ANCHORED": "Anclado",
|
||||||
"APPLICATIONS": "Aplicaciones",
|
"FLOATING": "Flotante",
|
||||||
"GAMES": "Juegos",
|
"STATIC": "Estático",
|
||||||
"SETTINGS": "Ajustes",
|
"SET": "Set",
|
||||||
"HELLO_USER": "¡Hola, {USER}!",
|
"WATCH": "Reloj",
|
||||||
"GENERAL_SETTINGS": "Ajustes generales",
|
"DASHBOARD": "Panel de control",
|
||||||
"APPLICATION_LAUNCHER": "Lanzador de aplicaciones",
|
"EDIT_MODE": "Modo edición",
|
||||||
"APP_SETTINGS": {
|
"SETTINGS": "Ajustes",
|
||||||
"HIDE_USERNAME": "Ocultar nombre de usuario",
|
"KEYBOARD": "Teclado",
|
||||||
"OPAQUE_BACKGROUND": "Fondo opaco",
|
"TASKBAR": "Barra de tareas",
|
||||||
"LOOK_AND_FEEL": "Apariencia y estilo",
|
|
||||||
"HIDE_GRAB_HELP": "Ocultar ayuda para agarrar",
|
|
||||||
"ANIMATION_SPEED": "Velocidad de animación de la IU",
|
|
||||||
"ROUND_MULTIPLIER": "Redondeo de bordes de la IU",
|
|
||||||
"USE_SKYBOX": "Activar skybox",
|
|
||||||
"USE_PASSTHROUGH": "Activar passthrough",
|
|
||||||
"CLOCK_12H": "Reloj de 12 horas",
|
|
||||||
"FEATURES": "Funciones",
|
"FEATURES": "Funciones",
|
||||||
"NOTIFICATIONS_ENABLED": "Habilitar notificaciones",
|
"OVERLAY": "Overlay",
|
||||||
"NOTIFICATIONS_SOUND_ENABLED": "Sonidos de notificación",
|
"SKYMAP": "Skymap",
|
||||||
"KEYBOARD_SOUND_ENABLED": "Sonidos del teclado",
|
"PLAYSPACE": "Espacio de juego",
|
||||||
"SPACE_DRAG_MULTIPLIER": "Multiplicador de arrastre espacial",
|
"D_PAD": "Cruceta"
|
||||||
"SPACE_DRAG_UNLOCKED": "Permitir arrastre del espacio en todos los ejes",
|
},
|
||||||
"SPACE_ROTATE_UNLOCKED": "Permitir rotación espacial en todos los ejes",
|
"ACTIONS": {
|
||||||
"BLOCK_GAME_INPUT": "Bloquear entrada del juego",
|
"RECENTER_PLAYSPACE": "Recentrar espacio de juego"
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignorar watch al bloquear la entrada",
|
},
|
||||||
"CONTROLS": "Controles",
|
"APP_LAUNCHER": {
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "El movimiento del ratón en el disparador",
|
"ASPECT": {
|
||||||
"LEFT_HANDED_MOUSE": "Ratón para zurdos",
|
"SEMI_TALL": "Semicomprimido vertical",
|
||||||
"ALLOW_SLIDING": "Interacción con el stick durante el agarre",
|
"SEMI_WIDE": "Semicomprimido",
|
||||||
"INVERT_SCROLL_DIRECTION_X": "Invertir dirección de desplazamiento horizontal",
|
"SQUARE": "Cuadrado",
|
||||||
"INVERT_SCROLL_DIRECTION_Y": "Invertir la dirección del desplazamiento vertical",
|
"TALL": "Vertical",
|
||||||
"SCROLL_SPEED": "Velocidad de desplazamiento",
|
"WIDE": "Ancho"
|
||||||
"LONG_PRESS_DURATION": "Duración de la pulsación larga",
|
|
||||||
"POINTER_LERP_FACTOR": "Suavizado del puntero",
|
|
||||||
"CLICK_FREEZE_TIME_MS": "Tiempo de congelación al hacer clic (ms)",
|
|
||||||
"MISC": "Miscelánea",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "Ejecutar aplicaciones en modo de compatibilidad por defecto",
|
|
||||||
"UPRIGHT_SCREEN_FIX": "Corrección de pantalla vertical",
|
|
||||||
"DOUBLE_CURSOR_FIX": "Solución de doble cursor",
|
|
||||||
"SCREEN_RENDER_DOWN": "Renderizar pantalla a menor resolución",
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Corrige pantallas en posición vertical en algunos escritorios",
|
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Habilita esto si ves 2 cursores",
|
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Ayuda con la precisión de los dobles clics",
|
|
||||||
"LEFT_HANDED_MOUSE_HELP": "Utilice esto si los botones del ratón están intercambiados",
|
|
||||||
"BLOCK_GAME_INPUT_HELP": "Bloquea toda la entrada cuando se pasa el cursor sobre un overlay",
|
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "No bloquear la entrada cuando el cursor está sobre la ventana",
|
|
||||||
"USE_SKYBOX_HELP": "Mostrar una skybox si no hay una aplicación de escena o passthrough",
|
|
||||||
"USE_PASSTHROUGH_HELP": "Permitir passthrough si el entorno de ejecución XR lo admite",
|
|
||||||
"SCREEN_RENDER_DOWN_HELP": "Ayuda a reducir el aliasing en pantallas de alta resolución",
|
|
||||||
"SETS_ON_WATCH": "Conjuntos en el reloj",
|
|
||||||
"TROUBLESHOOTING": "Solución de problemas",
|
|
||||||
"CLEAR_SAVED_STATE": "Borrar estado guardado",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "Limpiar tokens de PipeWire",
|
|
||||||
"DELETE_ALL_CONFIGS": "Borrar configuración",
|
|
||||||
"RESTART_SOFTWARE": "Reiniciar software",
|
|
||||||
"CLEAR_SAVED_STATE_HELP": "Restablecer sets y posiciones de superposición",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "Solicitar la selección de pantalla al iniciar la próxima vez",
|
|
||||||
"DELETE_ALL_CONFIGS_HELP": "Eliminar todos los archivos de configuración de conf.d",
|
|
||||||
"RESTART_SOFTWARE_HELP": "Aplicar la configuración que requiere un reinicio",
|
|
||||||
"CAPTURE_METHOD": "Captura de pantalla de Wayland",
|
|
||||||
"CAPTURE_METHOD_HELP": "Intente cambiar esta opción si\nexperimenta pantallas negras o con fallos",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK": "Clic del botón central del teclado",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK_HELP": "Modificador para usar al escribir\ncon láser púrpura",
|
|
||||||
"OPTION": {
|
|
||||||
"AUTO": "Automático",
|
|
||||||
"AUTO_HELP": "Copiar pantalla usando la GPU si es compatible,\nde lo contrario, GPU de PipeWire.",
|
|
||||||
"PIPEWIRE_HELP": "Captura de GPU rápida,\nestándar en todos los escritorios.",
|
|
||||||
"PW_FALLBACK_HELP": "Método lento con alto uso de CPU.\nPruébalo si PipeWire GPU no funciona",
|
|
||||||
"SCREENCOPY_GPU_HELP": "Rápido, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
|
|
||||||
"SCREENCOPY_HELP": "Lento, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
|
|
||||||
"NONE": "Ninguno",
|
|
||||||
"HMD_PINCH": "HMD + pellizco",
|
|
||||||
"EYE_PINCH": "Ojo + pellizco",
|
|
||||||
"EYE_ONLY": "Solo ojo",
|
|
||||||
"HMD_ONLY": "Solo HMD",
|
|
||||||
"NONE_INPUT_HELP": "No emular ratón y teclado.\nNo podrá interactuar con las pantallas.",
|
|
||||||
"UINPUT": "Emulación de dispositivo",
|
|
||||||
"UINPUT_HELP": "Utiliza el módulo uinput para emular un dispositivo.\nSu usuario debe estar en el grupo input.\nSe sabe que funciona bien en la mayoría de los escritorios.",
|
|
||||||
"WL_VIRTUAL": "Entrada virtual de Wayland",
|
|
||||||
"WL_VIRTUAL_HELP": "Enviar eventos al compositor de Wayland usando\nzwlr_virtual_pointer y zwp_virtual_keyboard.\nSolo funciona de forma fiable en algunos escritorios.\nNO funciona en KDE, GNOME o COSMIC."
|
|
||||||
},
|
},
|
||||||
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio",
|
"ASPECT_TITLE": "Relación de aspecto",
|
||||||
"HANDSFREE_POINTER": "Modo manos libres",
|
"AUTOSTART": "Iniciar automáticamente al arrancar",
|
||||||
"HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic.",
|
"LAUNCH": "Lanzar",
|
||||||
"UI_GRADIENT_INTENSITY": "Intensidad del degradado de la IU",
|
"MODE": {
|
||||||
"RESET_PLAYSPACE": "Restablecer espacio de juego",
|
"CAGE": "Modo de compatibilidad (Cage)",
|
||||||
"RESET_PLAYSPACE_HELP": "Borrar el desplazamiento del espacio de juego.",
|
"NATIVE": "Modo nativo"
|
||||||
|
},
|
||||||
|
"RES_TITLE": "Resolución"
|
||||||
|
},
|
||||||
|
"APP_SETTINGS": {
|
||||||
|
"ALLOW_SLIDING": "Interacción del stick al agarrar",
|
||||||
|
"ANIMATION_SPEED": "Velocidad de animación de la interfaz",
|
||||||
|
"AUTOSTART_APPS": "Aplicaciones al iniciar",
|
||||||
|
"BLOCK_GAME_INPUT": "Bloquear entrada del juego",
|
||||||
|
"BLOCK_GAME_INPUT_HELP": "Bloquea toda entrada cuando el cursor está sobre una superposición",
|
||||||
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignorar el reloj al bloquear la entrada",
|
||||||
|
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "No bloquear la entrada al pasar el cursor sobre el reloj",
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION": "Bloquear poses al interactuar con el teclado",
|
"BLOCK_POSES_ON_KBD_INTERACTION": "Bloquear poses al interactuar con el teclado",
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Bloquea que el juego reciba poses cuando el teclado está sobre él y 'Bloquear entrada del juego' está habilitado",
|
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Bloquea la recepción de poses del juego cuando el cursor está sobre el teclado y 'Bloquear entrada del juego' está activado",
|
||||||
"LANGUAGE": "Idioma",
|
|
||||||
"REQUIRES_RESTART": "Requiere reinicio",
|
|
||||||
"GRID_OPACITY": "Opacidad de la cuadrícula del suelo",
|
|
||||||
"GRID_OPACITY_HELP": "Opacidad de la cuadrícula del suelo cuando el skybox está habilitado",
|
|
||||||
"BROWSE_ONLINE_CATALOG": "Explorar catálogo en línea...",
|
|
||||||
"BROWSE_SKYMAPS": "Explorar skymaps",
|
|
||||||
"COLOR_KEYING": "Clave de color",
|
|
||||||
"NO_SKYMAPS_FOUND": "No se encontraron skymaps",
|
|
||||||
"SELECT_VARIANT": "Seleccionar variante",
|
|
||||||
"SHOW_WELCOME_SCREEN": "Mostrar pantalla de bienvenida",
|
|
||||||
"SKYBOX": "Skybox",
|
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "Esta skymap ya ha sido descargada. Selecciona la acción deseada.",
|
|
||||||
"WATCH_VIEW_ANGLE": "Ángulos de visión del Watch",
|
|
||||||
"WATCH_VIEW_ANGLE_HELP": "Controla cómo se desvanece el Watch",
|
|
||||||
"BINDINGS": {
|
"BINDINGS": {
|
||||||
"COMP": {
|
"COMP": {
|
||||||
"CLICK": "Click",
|
"CLICK": "Clic",
|
||||||
"FORCE": "Fuerza",
|
"FORCE": "Fuerza",
|
||||||
"TOUCH": "Tocar",
|
"TOUCH": "Toque",
|
||||||
"VALUE": "Valor",
|
"VALUE": "Valor",
|
||||||
"PROXIMITY": "Proximidad",
|
"PROXIMITY": "Proximidad",
|
||||||
"X_AXIS": "Eje X",
|
"X_AXIS": "Eje X",
|
||||||
|
|
@ -116,185 +58,292 @@
|
||||||
},
|
},
|
||||||
"TYPE": {
|
"TYPE": {
|
||||||
"BUMPER": "Bumper",
|
"BUMPER": "Bumper",
|
||||||
"DPAD_UP": "D-pad arriba",
|
"DPAD_UP": "Cruceta Arriba",
|
||||||
"DPAD_DOWN": "D-pad hacia abajo",
|
"DPAD_DOWN": "Cruceta Abajo",
|
||||||
"DPAD_LEFT": "D-pad izquierda",
|
"DPAD_LEFT": "Cruceta Izquierda",
|
||||||
"DPAD_RIGHT": "D-pad derecha",
|
"DPAD_RIGHT": "Cruceta Derecha",
|
||||||
"JOYSTICK": "Joystick",
|
"JOYSTICK": "Joystick",
|
||||||
"MENU": "Menú",
|
"MENU": "Menú",
|
||||||
"SHOULDER": "Hombro",
|
"SHOULDER": "Hombro",
|
||||||
"SQUEEZE": "Agarre",
|
"SQUEEZE": "Agarre",
|
||||||
"SYSTEM": "Sistema",
|
"SYSTEM": "Sistema",
|
||||||
"THUMBREST": "Thumbrest",
|
"THUMBREST": "Apoyo del pulgar",
|
||||||
"THUMBSTICK": "Stick analógico",
|
"THUMBSTICK": "Palanca",
|
||||||
"TRACKPAD": "Trackpad",
|
"TRACKPAD": "Trackpad",
|
||||||
"TRIGGER": "Gatillo",
|
"TRIGGER": "Gatillo",
|
||||||
"VIEW": "Ver"
|
"VIEW": "Vista"
|
||||||
},
|
},
|
||||||
"CLICK": {
|
"CLICK": {
|
||||||
"ANY": "Cualquiera",
|
"ANY": "Cualquiera",
|
||||||
"DOUBLE": "Doble toque",
|
"DOUBLE": "Doble toque",
|
||||||
"TRIPLE": "Triple toque",
|
"TRIPLE": "Triple toque",
|
||||||
"TYPE": "Número de toques"
|
"TYPE": "Cantidad de toques"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"CLICK": "Clic*",
|
"CLICK": "Clic*",
|
||||||
"GRAB": "Agarrar*",
|
"GRAB": "Agarre*",
|
||||||
"ALT_CLICK": "Ejecución de shell personalizada (establecer alt_click en la configuración)",
|
"ALT_CLICK": "Ejecutable de shell personalizado (configura alt_click en el archivo de config)",
|
||||||
"SHOW_HIDE": "Mostrar, ocultar, recentrar*",
|
"SHOW_HIDE": "Mostrar, ocultar, recentrar*",
|
||||||
"TOGGLE_DASHBOARD": "Alternar dashboard",
|
"TOGGLE_DASHBOARD": "Alternar tablero",
|
||||||
"SPACE_DRAG": "Arrastre del playspace",
|
"SPACE_DRAG": "Arrastre del espacio de juego",
|
||||||
"SPACE_ROTATE": "Rotar playspace",
|
"SPACE_ROTATE": "Rotar espacio de juego",
|
||||||
"SPACE_RESET": "Reinicio del Playspace",
|
"SPACE_RESET": "Restablecer espacio de juego",
|
||||||
"CLICK_MODIFIER_RIGHT": "Modificador de clic derecho",
|
"CLICK_MODIFIER_RIGHT": "Modificador de clic derecho",
|
||||||
"CLICK_MODIFIER_MIDDLE": "Modificador de clic central",
|
"CLICK_MODIFIER_MIDDLE": "Modificador de clic central",
|
||||||
"MOVE_MOUSE": "Mover ratón (si está desactivado por defecto)",
|
"MOVE_MOUSE": "Mover ratón (desactivado por defecto)",
|
||||||
"SCROLL": "Desplazamiento*"
|
"SCROLL": "Desplazar*"
|
||||||
},
|
},
|
||||||
"LEFT": "Izquierda",
|
"LEFT": "Izquierda",
|
||||||
"RIGHT": "Derecha",
|
"RIGHT": "Derecha",
|
||||||
"COMPONENT": "Tipo de actuación",
|
"COMPONENT": "Tipo de accionamiento",
|
||||||
"SUBPATH": "Control de actuación",
|
"SUBPATH": "Control a accionar",
|
||||||
"THRESHOLD": "Activar cuando supere el valor superior\nDesactivar cuando sea inferior al valor inferior"
|
"THRESHOLD": "Activar al superar el valor superior\nDesactivar al caer bajo el valor inferior"
|
||||||
},
|
},
|
||||||
|
"BROWSE_ONLINE_CATALOG": "Explorar catálogo en línea...",
|
||||||
|
"BROWSE_SKYMAPS": "Explorar skymaps",
|
||||||
|
"CAPTURE_METHOD": "Método de captura de pantalla",
|
||||||
|
"CAPTURE_METHOD_HELP": "Prueba a cambiar esto si tienes\npantallas negras o con errores",
|
||||||
|
"COLOR_KEYING": "Clave de color",
|
||||||
|
"COLOR_PALETTE": "Paleta de colores",
|
||||||
|
"COLOR_PALETTE_HELP": "Haz clic para explorar paletas de colores.\n¡Para crear las tuyas, visita la web!",
|
||||||
|
"COLOR_PALETTES": "Paletas de colores",
|
||||||
|
"COLOR_PALETTE_CURRENT": "Tema actualmente activo.",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "¡Añade tu propio tema personalizado!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Haz clic para abrir el manual web.",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS": "Limpiar tokens de PipeWire",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "Preguntar por la selección de pantalla al siguiente inicio",
|
||||||
|
"CLEAR_SAVED_STATE": "Borrar estado guardado",
|
||||||
|
"CLEAR_SAVED_STATE_HELP": "Restablecer sets y posiciones de los overlays",
|
||||||
|
"CLICK_FREEZE_TIME_MS": "Tiempo de congelación del clic (ms)",
|
||||||
|
"CLICK_FREEZE_TIME_MS_HELP": "Ayuda con la precisión del doble clic",
|
||||||
|
"CLOCK_12H": "Reloj de 12 horas",
|
||||||
|
"CONTROLS": "Controles",
|
||||||
|
"DELETE_ALL_CONFIGS": "Borrar configuración",
|
||||||
|
"DELETE_ALL_CONFIGS_HELP": "Elimina todos los archivos de configuración de conf.d",
|
||||||
|
"DOUBLE_CURSOR_FIX": "Corrección de doble cursor",
|
||||||
|
"DOUBLE_CURSOR_FIX_HELP": "Activa esto si ves 2 cursores",
|
||||||
|
"DEFAULT_OVERLAY_SCALE": "Tamaño predeterminado de la superposición",
|
||||||
|
"DEFAULT_OVERLAY_SCALE_HELP": "Aparecer nuevos overlays a esta escala.",
|
||||||
|
"DEFAULT_CURVATURE": "Curvatura predeterminada del overlay",
|
||||||
|
"DEFAULT_OPACITY": "Opacidad predeterminada del overlay",
|
||||||
|
"DEFAULT_POSITIONING": "Posicionamiento predeterminado del overlay",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "Solo se aplica a los overlays nuevos",
|
||||||
"ENABLED": "Activado",
|
"ENABLED": "Activado",
|
||||||
|
"FEATURES": "Funciones",
|
||||||
|
"FOCUS_FOLLOWS_MOUSE_MODE": "Mover ratón al tocar el gatillo",
|
||||||
|
"HANDSFREE_POINTER": "Modo manos libres",
|
||||||
|
"HANDSFREE_POINTER_HELP": "Entrada a usar cuando no haya controladores de movimiento.\nPinza izquierda para agarrar, derecha para hacer clic.",
|
||||||
|
"HANDSFREE_ALT_TAB": "Apuntado del selector de apps",
|
||||||
|
"HANDSFREE_ALT_TAB_HELP": "Mantén presionado Super+X, apunta a la ventana deseada y suelta para cambiar el foco.",
|
||||||
|
"HIDE_GRAB_HELP": "Ocultar ayuda de agarre",
|
||||||
|
"HIDE_USERNAME": "Ocultar nombre de usuario",
|
||||||
"INPUT_EMULATION_METHOD": "Método de emulación de entrada",
|
"INPUT_EMULATION_METHOD": "Método de emulación de entrada",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "Prueba a cambiar esto en caso de que la entrada del\nratón o el teclado no se registre.",
|
"INPUT_EMULATION_METHOD_HELP": "Prueba a cambiar esto si el ratón o\nel teclado no responden.",
|
||||||
"INPUT_PROFILES": "Cambiar la configuración de entrada",
|
"INPUT_CAPTURE_METHOD": "Método de captura de entrada",
|
||||||
"INPUT_PROFILES_HELP": "Vinculaciones de entrada del controlador OpenXR",
|
"INPUT_CAPTURE_METHOD_HELP": "Permite usar periféricos físicos dentro de WayVR.\n Super+Z: Alternar entrada entre WayVR y el escritorio real\n Super+X: Alternar entre aplicaciones de WayVR",
|
||||||
"NOT_SUPPORTED": "No compatible",
|
"INPUT_PROFILES": "Cambiar asignación de controles",
|
||||||
"ENABLE_WATCH": "Activar watch",
|
"INPUT_PROFILES_HELP": "Asignaciones de entrada del controlador OpenXR",
|
||||||
"SPACE_DRAG": "Space drag",
|
"INVERT_SCROLL_DIRECTION_X": "Invertir dirección del desplazamiento horizontal",
|
||||||
|
"INVERT_SCROLL_DIRECTION_Y": "Invertir dirección del desplazamiento vertical",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK": "Clic central del teclado",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK_HELP": "Modificador al escribir\ncon el láser púrpura",
|
||||||
|
"KEYBOARD_SOUND_ENABLED": "Sonidos del teclado",
|
||||||
|
"LANGUAGE": "Idioma",
|
||||||
|
"LEFT_HANDED_MOUSE": "Mouse para zurdos",
|
||||||
|
"LEFT_HANDED_MOUSE_HELP": "Úsalo si los botones del ratón están invertidos",
|
||||||
|
"LONG_PRESS_DURATION": "Duración de pulsación larga",
|
||||||
|
"LOOK_AND_FEEL": "Apariencia",
|
||||||
|
"MISC": "Diversos",
|
||||||
|
"NOTIFICATIONS_ENABLED": "Habilitar notificaciones",
|
||||||
|
"NOTIFICATIONS_SOUND_ENABLED": "Sonidos de notificación",
|
||||||
|
"NOT_SUPPORTED": "No soportado",
|
||||||
|
"NO_SKYMAPS_FOUND": "No se encontraron skymaps",
|
||||||
|
"OPAQUE_BACKGROUND": "Fondo opaco",
|
||||||
|
"OPTION": {
|
||||||
|
"ANCHORED_HELP": "Se mueve con el marcador central. Recomendado.",
|
||||||
|
"FLOATING_HELP": "Se mueve independientemente y se recentra.\nFácil de perder; no recomendado.",
|
||||||
|
"STATIC_HELP": "Se mantiene fijo respecto al mundo.",
|
||||||
|
"AUTO": "Automático",
|
||||||
|
"AUTO_HELP": "ScreenCopy GPU si es compatible,\nsi no, PipeWire GPU.",
|
||||||
|
"EYE_ONLY": "Láser ocular",
|
||||||
|
"EYE_PINCH": "Ojo + pinza",
|
||||||
|
"HMD_ONLY": "Láser del HMD",
|
||||||
|
"HMD_PINCH": "HMD + pellizco",
|
||||||
|
"NONE": "Ninguno",
|
||||||
|
"NONE_INPUT_HELP": "No emular ratón ni teclado.\nNo podrás interactuar con las pantallas.",
|
||||||
|
"NONE_INPUT_CAPTURE_HELP": "No capturar teclado ni ratón.\nNo podrás usar el ratón o teclado físico en las \naplicaciones lanzadas dentro de WayVR.",
|
||||||
|
"PIPEWIRE_HELP": "Captura de GPU rápida,\nestándar en todos los escritorios.",
|
||||||
|
"PW_FALLBACK_HELP": "Método lento con alto uso de CPU.\nPruébalo si PipeWire GPU no funciona",
|
||||||
|
"SCREENCOPY_GPU_HELP": "Rápido, sin ventanas emergentes al compartir pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
|
||||||
|
"SCREENCOPY_HELP": "Lento, sin ventanas emergentes al compartir pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
|
||||||
|
"UINPUT": "Emulación de dispositivo",
|
||||||
|
"UINPUT_HELP": "Usa el módulo uinput para emular un dispositivo.\nFunciona bien en la mayoría de los escritorios.",
|
||||||
|
"EVDEV_HELP": "Captura los dispositivos de entrada para uso exclusivo.\nTu usuario debe pertenecer al grupo \"input\".",
|
||||||
|
"WL_VIRTUAL": "Entrada virtual de Wayland",
|
||||||
|
"WL_VIRTUAL_HELP": "Envía eventos al compositor Wayland usando\nzwlr_virtual_pointer y zwp_virtual_keyboard.\nSolo funciona de forma fiable en algunos escritorios.\nNO funciona en KDE, GNOME o COSMIC."
|
||||||
|
},
|
||||||
|
"POINTER_ACCELERATION": "Aceleración del ratón",
|
||||||
|
"POINTER_ACCELERATION_HELP": "Act.: Aceleración adaptativa del ratón\nDesact.: Velocidad constante",
|
||||||
|
"POINTER_LERP_FACTOR": "Suavizado del puntero",
|
||||||
|
"POINTER_SPEED": "Velocidad del ratón",
|
||||||
|
"REQUIRES_RESTART": "Requiere reiniciar",
|
||||||
|
"RESET_PLAYSPACE": "Restablecer espacio de juego",
|
||||||
|
"RESET_PLAYSPACE_HELP": "Elimina el desplazamiento del espacio de juego.",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "Guardar centro del espacio de juego",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "Usa el espacio de juego actual para el comando de reiniciar espacio de juego.",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "Reiniciar centro del espacio de juego",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "Restablece el centro del espacio de juego definido previamente.",
|
||||||
|
"RESTART_SOFTWARE": "Reiniciar software",
|
||||||
|
"RESTART_SOFTWARE_HELP": "Aplicar ajustes que requieren reiniciar",
|
||||||
|
"ROUND_MULTIPLIER": "Redondeo de bordes de la UI",
|
||||||
|
"SCREEN_RENDER_DOWN": "Renderizar pantalla a resolución menor",
|
||||||
|
"SCREEN_RENDER_DOWN_HELP": "Ayuda con el aliasing en pantallas de alta resolución",
|
||||||
|
"SCROLL_SPEED": "Velocidad de desplazamiento",
|
||||||
|
"SELECT_VARIANT": "Seleccionar variante",
|
||||||
|
"SNAP_ANGLE_DEG": "Ángulo de ajuste de inclinación y rotación de ventana",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "Las ventanas agarradas se ajustan a este ángulo en los ejes de cabeceo y balanceo.",
|
||||||
|
"ENABLE_WATCH": "Habilitar reloj",
|
||||||
|
"SETS_ON_WATCH": "Sets en el reloj",
|
||||||
|
"SHOW_WELCOME_SCREEN": "Mostrar pantalla de bienvenida",
|
||||||
|
"SKYBOX": "Skymap",
|
||||||
|
"SKYMAP_ALREADY_DOWNLOADED": "Este skymap ya está descargado. Selecciona la acción deseada.",
|
||||||
|
"SPACE_DRAG": "Espacio de juego",
|
||||||
|
"SPACE_DRAG_MULTIPLIER": "Multiplicador de Space-drag",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "Dejar overlays atrás al mover el espacio de juego",
|
||||||
|
"SPACE_DRAG_UNLOCKED": "Permitir espacio-drag en todos los ejes",
|
||||||
"SPACE_GRAVITY_DAMPING": "Amortiguación",
|
"SPACE_GRAVITY_DAMPING": "Amortiguación",
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "Resistencia artificial para ralentizar el movimiento. 0.1 - alta resistencia, 1.0 - sin resistencia",
|
"SPACE_GRAVITY_DAMPING_HELP": "Resistencia artificial para frenar el movimiento. 0.1 - mucha resistencia, 1.0 - sin resistencia",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH": "Fuerza de lanzamiento",
|
"SPACE_GRAVITY_FLING_STRENGTH": "Fuerza de impulso",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Multiplicador de intensidad de la fuerza de lanzamiento gravitacional tras el space-drag.\n0.0 - sin movimiento alguno, 2.0 - doble intensidad",
|
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Multiplicador de la intensidad de la fuerza de lanzamiento gravitacional tras el space-drag.\n0.0 - sin movimiento, 2.0 - intensidad doble",
|
||||||
"SPACE_GRAVITY_GRAVITY": "Gravedad",
|
"SPACE_GRAVITY_GRAVITY": "Gravedad",
|
||||||
"SPACE_GRAVITY_GRAVITY_HELP": "Cantidad de fuerza hacia abajo. 0.0 - sin gravedad",
|
"SPACE_GRAVITY_GRAVITY_HELP": "Cantidad de fuerza hacia abajo. 0.0 = sin gravedad",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION": "Fricción del suelo",
|
"SPACE_GRAVITY_GROUND_FRICTION": "Fricción del suelo",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Cantidad de fricción que te ralentiza si estás tocando el suelo.\n0.0 - sin fricción (como si fuera hielo), 1.0 - superficie rugosa",
|
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Cantidad de fricción que te frena al tocar el suelo.\n0.0 - sin fricción (como sobre hielo), 1.0 - superficie rugosa",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altura del suelo",
|
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altura del suelo",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posición Y donde se encuentra el suelo. La gravedad se detiene cuando alcanzas esta altura.",
|
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posición Y donde se encuentra el suelo. La gravedad se detiene al alcanzar esta altura.",
|
||||||
"SAVE": "Guardar",
|
"SPACE_ROTATE_UNLOCKED": "Permitir rotación del espacio en todos los ejes",
|
||||||
"CANCEL": "Cancelar",
|
"TROUBLESHOOTING": "Solución de problemas",
|
||||||
|
"UI_GRADIENT_INTENSITY": "Intensidad del degradado de la interfaz",
|
||||||
|
"UPRIGHT_SCREEN_FIX": "Corrección de pantalla vertical",
|
||||||
|
"UPRIGHT_SCREEN_FIX_HELP": "Corrige pantallas verticales en algunos escritorios",
|
||||||
|
"USE_PASSTHROUGH": "Activar passthrough",
|
||||||
|
"USE_PASSTHROUGH_HELP": "Permite el passthrough si el entorno XR lo soporta",
|
||||||
|
"USE_SKYBOX": "Mostrar skymap",
|
||||||
|
"USE_SKYBOX_HELP": "Mostrar un skymap si no hay una aplicación de escena o passthrough",
|
||||||
|
"WATCH_VIEW_ANGLE": "Ángulos de visión del reloj",
|
||||||
|
"WATCH_VIEW_ANGLE_HELP": "Controla cómo se desvanece el reloj",
|
||||||
"WHISPER": {
|
"WHISPER": {
|
||||||
"NEED_TO_DOWNLOAD_MODEL": "El modelo seleccionado debe ser descargado.\n¿Deseas descargarlo ahora?",
|
"NEED_TO_DOWNLOAD_MODEL": "El modelo seleccionado necesita descargarse.\n¿Descargarlo ahora?",
|
||||||
"REMOVE_UNUSED_MODELS": "Estás desactivando la función de voz a texto.\n¿Te gustaría eliminar los modelos de Whisper descargados para liberar espacio?"
|
"REMOVE_UNUSED_MODELS": "Estás desactivando la función de voz a texto.\n¿Quieres eliminar los modelos de Whisper descargados para liberar espacio?"
|
||||||
},
|
},
|
||||||
"WHISPER_MODEL": "Modelo de voz a texto",
|
"WHISPER_MODEL": "Modelo de dictado",
|
||||||
"WHISPER_MODEL_HELP": "Modelo de Whisper a utilizar.\nLos modelos más grandes producen\nresultados más precisos, pero consumen más VRAM."
|
"WHISPER_MODEL_HELP": "Modelo de Whisper a utilizar.\nLos modelos más grandes dan resultados\nmás precisos, pero consumen más VRAM.",
|
||||||
|
"GRID_OPACITY": "Opacidad de la rejilla del suelo",
|
||||||
|
"GRID_OPACITY_HELP": "Opacidad de la rejilla del suelo cuando el skymap está activado",
|
||||||
|
"XWAYLAND_BY_DEFAULT": "Ejecutar apps en modo de compatibilidad por defecto",
|
||||||
|
"SAVE": "Guardar",
|
||||||
|
"CANCEL": "Cancelar"
|
||||||
},
|
},
|
||||||
"HELLO": "¡Hola!",
|
"APPLICATION_LAUNCHER": "Lanzador de aplicaciones",
|
||||||
"AUDIO": {
|
|
||||||
"VOLUME": "Volumen",
|
|
||||||
"SETTINGS": "Configuración de audio",
|
|
||||||
"AUTO_SWITCH_TO_VR_AUDIO": "Conmutar automáticamente al audio VR",
|
|
||||||
"SPEAKERS": "Altavoces",
|
|
||||||
"MICROPHONES": "Micrófonos",
|
|
||||||
"CARDS": "Tarjetas",
|
|
||||||
"SELECT_AUDIO_CARD_PROFILE": "Seleccionar perfil de tarjeta de audio",
|
|
||||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "No se encontraron altavoces VR. Actívelos manualmente.",
|
|
||||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "No se encontró micrófono VR. Actívelo manualmente.",
|
|
||||||
"FAILED_TO_SWITCH_MICROPHONE": "No se pudo cambiar el micrófono",
|
|
||||||
"MICROPHONE_SET_SUCCESSFULLY": "Micrófono configurado correctamente",
|
|
||||||
"SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente"
|
|
||||||
},
|
|
||||||
"ACTIONS": {
|
|
||||||
"RECENTER_PLAYSPACE": "Re-centrar espacio de juego"
|
|
||||||
},
|
|
||||||
"POPUP_ADD_DISPLAY": {
|
|
||||||
"RESOLUTION": "Resolución"
|
|
||||||
},
|
|
||||||
"WIDTH": "Ancho",
|
|
||||||
"HEIGHT": "Altura",
|
|
||||||
"HIDE": "Ocultar",
|
|
||||||
"REMOVE": "Eliminar",
|
|
||||||
"SHOW": "Mostrar",
|
|
||||||
"FAILED_TO_LAUNCH_APPLICATION": "No se pudo iniciar la aplicación:",
|
|
||||||
"APPLICATION_STARTED": "Aplicación iniciada",
|
"APPLICATION_STARTED": "Aplicación iniciada",
|
||||||
|
"APPLICATIONS": "Aplicaciones",
|
||||||
|
"AUDIO": {
|
||||||
|
"AUTO_SWITCH_TO_VR_AUDIO": "Cambiar automáticamente al audio de VR",
|
||||||
|
"CARDS": "Tarjetas",
|
||||||
|
"FAILED_TO_SWITCH_MICROPHONE": "Error al cambiar el micrófono",
|
||||||
|
"MICROPHONE_SET_SUCCESSFULLY": "Micrófono configurado correctamente",
|
||||||
|
"MICROPHONES": "Micrófonos",
|
||||||
|
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "No se encontró micrófono de VR. Cámbialo manualmente.",
|
||||||
|
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "No se encontraron altavoces de VR. Cámbialos manualmente.",
|
||||||
|
"SELECT_AUDIO_CARD_PROFILE": "Selecciona el perfil de la tarjeta de sonido",
|
||||||
|
"SETTINGS": "Ajustes de audio",
|
||||||
|
"SPEAKERS": "Altavoces",
|
||||||
|
"SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente",
|
||||||
|
"VOLUME": "Volumen"
|
||||||
|
},
|
||||||
"CLOSE_WINDOW": "Cerrar ventana",
|
"CLOSE_WINDOW": "Cerrar ventana",
|
||||||
"GAME_LIST": {
|
|
||||||
"NO_GAMES_FOUND": "No se encontraron juegos",
|
|
||||||
"RUNNING_GAMES_LIST": "Lista de juegos en ejecución"
|
|
||||||
},
|
|
||||||
"TERMINATE_PROCESS": "Finalizar proceso",
|
|
||||||
"GAME_LAUNCHED": "Juego lanzado",
|
|
||||||
"APP_LAUNCHER": {
|
|
||||||
"MODE": {
|
|
||||||
"NATIVE": "Modo nativo",
|
|
||||||
"CAGE": "Modo de compatibilidad (Cage)"
|
|
||||||
},
|
|
||||||
"RES_TITLE": "Resolución",
|
|
||||||
"ASPECT_TITLE": "Aspecto",
|
|
||||||
"ASPECT": {
|
|
||||||
"WIDE": "Ancho",
|
|
||||||
"SEMI_WIDE": "Semi-ancho",
|
|
||||||
"SQUARE": "Cuadrado",
|
|
||||||
"SEMI_TALL": "Semi alto",
|
|
||||||
"TALL": "Alto"
|
|
||||||
},
|
|
||||||
"POS_TITLE": "Posicionamiento",
|
|
||||||
"POS": {
|
|
||||||
"FLOATING": "Flotante",
|
|
||||||
"ANCHORED": "Anclado",
|
|
||||||
"STATIC": "Estático",
|
|
||||||
"FLOATING_HELP": "Se mueve independientemente, se recentra al mostrarse.",
|
|
||||||
"ANCHORED_HELP": "Se mantiene en su lugar con respecto al marcador central.",
|
|
||||||
"STATIC_HELP": "No pertenece a ningún conjunto. No se recentra."
|
|
||||||
},
|
|
||||||
"AUTOSTART": "Ejecutar automáticamente al inicio",
|
|
||||||
"LAUNCH": "Iniciar"
|
|
||||||
},
|
|
||||||
"DISPLAY_BRIGHTNESS": "Brillo de la pantalla",
|
|
||||||
"PROCESS_LIST": "Lista de procesos",
|
|
||||||
"REFRESH": "Actualizar",
|
|
||||||
"PROCESS": {
|
|
||||||
"STOP": "Detener",
|
|
||||||
"FORCE_KILL": "Forzar cierre"
|
|
||||||
},
|
|
||||||
"DEBUG_INFO": "Información de depuración",
|
|
||||||
"CREATION_DATE": "Fecha de creación",
|
"CREATION_DATE": "Fecha de creación",
|
||||||
"DOWNLOADER": "Descargador",
|
"DEBUG_INFO": "Info de depuración",
|
||||||
"DOWNLOAD_AGAIN": "Descargar de nuevo",
|
"DISPLAY_BRIGHTNESS": "Brillo de pantalla",
|
||||||
"DOWNLOADING_FILE": "Descargando archivo...",
|
|
||||||
"GETTING_STARTED": "Primeros pasos",
|
|
||||||
"MODIFICATION_DATE": "Fecha de modificación",
|
|
||||||
"LOADING": "Cargando...",
|
|
||||||
"APPLY": "Aplicar",
|
|
||||||
"RELOAD_FROM_DISK": "Recargar desde el disco",
|
|
||||||
"TARGET_PATH": "Ruta de destino",
|
|
||||||
"VERSION": "Versión",
|
|
||||||
"DONATE": {
|
"DONATE": {
|
||||||
"SUPPORT_US": "Apóyanos",
|
"SUPPORT_US": "Apóyanos",
|
||||||
"DESCRIPTION": "Somos un pequeño equipo de 2 desarrolladores que creamos WayVR en nuestro tiempo libre. Si disfrutas usando este software, por favor considera apoyarnos; cada donación nos ayuda a seguir adelante.",
|
"DESCRIPTION": "Somos un pequeño equipo de 2 desarrolladores creando WayVR en nuestro tiempo libre. Si disfrutas usando este software, considera apoyarnos; cada donación nos ayuda a seguir adelante.",
|
||||||
"BUTTON_TOOLTIP": "Donar vía Open Collective",
|
"THANK_YOU_WAYVR": "¡Gracias del equipo de WayVR!",
|
||||||
|
"BUTTON_TOOLTIP": "Dona a través de Open Collective",
|
||||||
"CURRENT_SUPPORTERS": "Colaboradores actuales",
|
"CURRENT_SUPPORTERS": "Colaboradores actuales",
|
||||||
"THANK_YOU_WAYVR": "¡Gracias de parte del equipo de WayVR!"
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Apoyado por {USER}|Gracias a {USER}|Con el apoyo de {USER}|Patrocinado por {USER}|Un aporte especial de {USER}|Impulsado por {USER}|Haciendo esto posible: {USER}|Sostenible gracias a {USER}|Un agradecimiento a {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "Un gran impulso de {USER}|Todo es gracias a {USER}|Con todo el cariño de {USER}|El motor de hoy: {USER}|Sumando valor con {USER}|Haciendo crecer el proyecto: {USER}|De corazón, gracias a {USER}|Con el respaldo de {USER}|La chispa del día: {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "¡Un nivel leyenda: {USER}!|Energía pura gracias a {USER}|Nuestra estrella del día: {USER}|El MVP de hoy: {USER}|Rescatando el día: {USER}|Sosteniendo la aplicación: {USER}|El combustible secreto: {USER}|Manteniendo la cordura: {USER}|Conversor de café en código: {USER}|Salvando la producción: {USER}|¡Simplemente increíble: {USER}!|El corazón de todo: {USER}"
|
||||||
},
|
},
|
||||||
|
"DOWNLOAD": "Descargar",
|
||||||
|
"DOWNLOADER": "Descargador",
|
||||||
"WELCOME": {
|
"WELCOME": {
|
||||||
"ALL_SET": "¡Todo listo!",
|
"ALL_SET": "¡Todo listo!",
|
||||||
"BASICS": "Estos conceptos básicos te permitirán empezar a usar WayVR con facilidad.",
|
"BASICS": "Estos conceptos básicos te permitirán empezar a usar WayVR con facilidad.",
|
||||||
"CENTER_MARKER": "El marcador central determina el centro de tu set.",
|
"CENTER_MARKER": "El marcador de centro es lo que aparecerá frente a ti al recentrar. ¡Coloca los overlays alrededor de él!",
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "Pulsa dos veces B (en Index) o Y (en Meta) para alternar la visibilidad de tu espacio de trabajo. Pruébalo ahora.",
|
"DOUBLE_PRESS_TO_TOGGLE": "Pulsa dos veces B (en Index) o Y (en Meta) para mostrar, recentrar u ocultar tu Set. Pruébalo ahora.",
|
||||||
"FEATURES_DOCUMENTATION": "Hay muchas otras funciones que merece la pena personalizar. Para más información, consulta la documentación en",
|
"FEATURES_DOCUMENTATION": "Hay muchas otras funciones que vale la pena personalizar. Para más información, consulta la documentación en",
|
||||||
"FINISH_TUTORIAL": "Finalizar tutorial",
|
"FINISH_TUTORIAL": "Finalizar tutorial",
|
||||||
"GRAB_BOTH_HANDS": "Agarra el elemento con ambas manos si quieres mover un overlay específico en tu set.",
|
"GRAB_BOTH_HANDS": "Agarralo con ambas manos si quieres mover un overlay específico de tu set.",
|
||||||
"GRAB_ONE_HAND": "Agárralo con una mano para mover tu set.",
|
"GRAB_ONE_HAND": "Agarralo con una mano para mover tu set.",
|
||||||
"GREETING": "¡Hola!",
|
"GREETING": "¡Hola!",
|
||||||
"GUIDE_INTRO": "Permítenos guiarte en tus primeros pasos.",
|
"GUIDE_INTRO": "Déjanos guiarte en tus primeros pasos.",
|
||||||
"LASER_COLORS": "Colores del láser",
|
"LASER_COLORS": "Colores del láser",
|
||||||
"LASER_FUNCTIONALITY": "Gran parte de la funcionalidad de WayVR depende del color de láser que se utilice para interactuar con un elemento de la interfaz. ¡No hace falta pulsar estos botones, solo tocarlos!",
|
"LASER_FUNCTIONALITY": "Gran parte de la funcionalidad de WayVR depende del color del láser usado para interactuar con un elemento de la interfaz. ¡No hace falta pulsar los botones, basta con tocarlos!",
|
||||||
"LAST_PAGE_INFO": "Este tutorial dejará de aparecer una vez que llegues a la última página.",
|
"LAST_PAGE_INFO": "Este tutorial dejará de aparecer una vez que llegues a la última página.",
|
||||||
"LOOK_AT_LEFT_WRIST": "Mira tu muñeca izquierda. Ese es tu watch.",
|
"LOOK_AT_LEFT_WRIST": "Mira tu muñeca izquierda. Ahí tienes tu reloj.",
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Modo de clic central: Láser morado",
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Modo clic central: Láser púrpura",
|
||||||
"MOVING_YOUR_SET": "Moviendo tu set",
|
"MOVING_YOUR_SET": "Mover tu set",
|
||||||
"NEXT_BUTTON": "Pulsa el botón \"Siguiente\" de abajo para comenzar.",
|
"NEXT_BUTTON": "Pulsa el botón Siguiente abajo para empezar.",
|
||||||
"REGULAR_MODE_BLUE_LASER": "— Modo Regular: Láser azul",
|
"REGULAR_MODE_BLUE_LASER": "Modo normal: Láser azul",
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposiciona esta ventana usando la acción de agarre de tu controlador.",
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposiciona esta ventana usando el agarre (grip) de tu controlador.",
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Modo de clic derecho: Láser naranja",
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "Modo clic derecho: Láser naranja",
|
||||||
"THANKS_FOR_INSTALLING": "¡Gracias por instalar WayVR!",
|
"THANKS_FOR_INSTALLING": "¡Gracias por instalar WayVR!",
|
||||||
"WATCH": "Watch",
|
"WATCH": "Reloj",
|
||||||
"WORKING_SET": "Set de trabajo"
|
"WORKING_SET": "Set actual"
|
||||||
},
|
},
|
||||||
"DOWNLOAD": "Descargar"
|
"DOWNLOAD_AGAIN": "Descargar de nuevo",
|
||||||
|
"DOWNLOADING_FILE": "Descargando archivo...",
|
||||||
|
"FAILED_TO_LAUNCH_APPLICATION": "Error al lanzar la aplicación:",
|
||||||
|
"GAME_LAUNCHED": "Juego iniciado",
|
||||||
|
"GAME_LIST": {
|
||||||
|
"NO_GAMES_FOUND": "No se encontraron juegos",
|
||||||
|
"RUNNING_GAMES_LIST": "Lista de juegos activos"
|
||||||
|
},
|
||||||
|
"GAMES": "Juegos",
|
||||||
|
"GENERAL_SETTINGS": "Ajustes generales",
|
||||||
|
"GETTING_STARTED": "Primeros pasos",
|
||||||
|
"HEIGHT": "Altura",
|
||||||
|
"HELLO": "¡Hola!",
|
||||||
|
"HELLO_USER": "¡Hola, {USER}!",
|
||||||
|
"HIDE": "Ocultar",
|
||||||
|
"HOME_SCREEN": "Inicio",
|
||||||
|
"MODIFICATION_DATE": "Fecha de modificación",
|
||||||
|
"MONADO_RUNTIME": "Runtime de Monado",
|
||||||
|
"LOADING": "Cargando...",
|
||||||
|
"POPUP_ADD_DISPLAY": {
|
||||||
|
"RESOLUTION": "Resolución"
|
||||||
|
},
|
||||||
|
"PROCESS": {
|
||||||
|
"FORCE_KILL": "Forzar cierre",
|
||||||
|
"STOP": "Detener"
|
||||||
|
},
|
||||||
|
"PROCESS_LIST": "Lista de procesos",
|
||||||
|
"REFRESH": "Actualizar",
|
||||||
|
"REMOVE": "Eliminar",
|
||||||
|
"APPLY": "Aplicar",
|
||||||
|
"RELOAD_FROM_DISK": "Recargar desde disco",
|
||||||
|
"SETTINGS": "Ajustes",
|
||||||
|
"SHOW": "Mostrar",
|
||||||
|
"TARGET_PATH": "Ruta de destino",
|
||||||
|
"TERMINATE_PROCESS": "Terminar proceso",
|
||||||
|
"VERSION": "Versión",
|
||||||
|
"WIDTH": "Ancho",
|
||||||
|
"PINNED_APPS": "Aplicaciones fijadas",
|
||||||
|
"SAVED_TO_FAVOURITES": "Guardado en aplicaciones fijadas",
|
||||||
|
"ADD_TO_FAVOURITES": "Añadir a aplicaciones fijadas",
|
||||||
|
"ADD_TO_FAVOURITES_HINT": "Guardar ajuste y fijarlo al cajón de aplicaciones",
|
||||||
|
"REMOVE_FROM_FAVOURITES": "Quitar de aplicaciones fijadas",
|
||||||
|
"EMPTY": "Vacío"
|
||||||
}
|
}
|
||||||
|
|
@ -1,130 +1,51 @@
|
||||||
{
|
{
|
||||||
|
"DEFINITIONS": {
|
||||||
|
"ANCHORED": "Ancorato",
|
||||||
|
"FLOATING": "Fluttuante",
|
||||||
|
"STATIC": "Statico",
|
||||||
|
"SET": "Set",
|
||||||
|
"WATCH": "Orologio",
|
||||||
|
"DASHBOARD": "Dashboard",
|
||||||
|
"EDIT_MODE": "Modalità modifica",
|
||||||
|
"SETTINGS": "Impostazioni",
|
||||||
|
"KEYBOARD": "Tastiera",
|
||||||
|
"TASKBAR": "Barra delle applicazioni",
|
||||||
|
"FEATURES": "Funzionalità",
|
||||||
|
"OVERLAY": "Overlay",
|
||||||
|
"SKYMAP": "Skymap",
|
||||||
|
"PLAYSPACE": "Playspace",
|
||||||
|
"D_PAD": "D-pad"
|
||||||
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"RECENTER_PLAYSPACE": "Recentra lo spazio di gioco"
|
"RECENTER_PLAYSPACE": "Ricentra playspace"
|
||||||
},
|
},
|
||||||
"APP_LAUNCHER": {
|
"APP_LAUNCHER": {
|
||||||
"ASPECT": {
|
"ASPECT": {
|
||||||
"SEMI_TALL": "Semi-alto",
|
"SEMI_TALL": "Semi-verticale",
|
||||||
"SEMI_WIDE": "Semi-ampio",
|
"SEMI_WIDE": "Semi-ampio",
|
||||||
"SQUARE": "Quadrato",
|
"SQUARE": "Quadrato",
|
||||||
"TALL": "Alto",
|
"TALL": "Verticale",
|
||||||
"WIDE": "Ampio"
|
"WIDE": "Widescreen"
|
||||||
},
|
},
|
||||||
"ASPECT_TITLE": "Proporzioni",
|
"ASPECT_TITLE": "Formato",
|
||||||
"AUTOSTART": "Avvia automaticamente all'avvio",
|
"AUTOSTART": "Avvia automaticamente all'avvio",
|
||||||
"LAUNCH": "Avvia",
|
"LAUNCH": "Avvia",
|
||||||
"MODE": {
|
"MODE": {
|
||||||
"CAGE": "Modalità compatibilità (Cage)",
|
"CAGE": "Modalità compatibilità (Cage)",
|
||||||
"NATIVE": "Modalità nativa"
|
"NATIVE": "Modalità nativa"
|
||||||
},
|
},
|
||||||
"POS": {
|
|
||||||
"ANCHORED": "Ancorato",
|
|
||||||
"ANCHORED_HELP": "Rimane fermo rispetto al marcatore centrale.",
|
|
||||||
"FLOATING": "Fluttuante",
|
|
||||||
"FLOATING_HELP": "Si muove in modo indipendente, si recentra quando viene mostrato.",
|
|
||||||
"STATIC": "Statico",
|
|
||||||
"STATIC_HELP": "Non fa parte di alcun set. Non recentra."
|
|
||||||
},
|
|
||||||
"POS_TITLE": "Posizionamento",
|
|
||||||
"RES_TITLE": "Risoluzione"
|
"RES_TITLE": "Risoluzione"
|
||||||
},
|
},
|
||||||
"APP_SETTINGS": {
|
"APP_SETTINGS": {
|
||||||
"ALLOW_SLIDING": "Interazione tramite stick durante l'afferrare",
|
"ALLOW_SLIDING": "Interazione stick durante il grab",
|
||||||
"ANIMATION_SPEED": "Velocità dell'animazione dell'interfaccia utente",
|
"ANIMATION_SPEED": "Velocità animazioni UI",
|
||||||
"BLOCK_GAME_INPUT": "Blocca l'input di gioco",
|
"AUTOSTART_APPS": "App all'avvio",
|
||||||
"BLOCK_GAME_INPUT_HELP": "Blocca tutti gli input quando il cursore è sopra un overlay",
|
"BLOCK_GAME_INPUT": "Blocca input di gioco",
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignora il Watch quando si blocca l'input",
|
"BLOCK_GAME_INPUT_HELP": "Blocca ogni input quando un overlay è selezionato",
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Non bloccare l'input quando il watch è evidenziato",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignora l'orologio durante il blocco dell'input",
|
||||||
"CAPTURE_METHOD": "Acquisizione dello schermo Wayland",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Non bloccare l'input quando il cursore è sull'orologio",
|
||||||
"CAPTURE_METHOD_HELP": "Prova a modificare questa impostazione se riscontri schermate nere o con artefatti.",
|
"BLOCK_POSES_ON_KBD_INTERACTION": "Blocca pose durante l'interazione con la tastiera",
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "Cancella i token PipeWire",
|
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blocca la ricezione delle pose del gioco quando il cursore è sul tastiera e l'opzione 'Blocca input gioco' è attiva",
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "Richiedi la selezione dello schermo all'avvio successivo",
|
|
||||||
"CLEAR_SAVED_STATE": "Cancella stato salvato",
|
|
||||||
"CLEAR_SAVED_STATE_HELP": "Ripristina set e posizioni degli overlay",
|
|
||||||
"CLICK_FREEZE_TIME_MS": "Tempo di congelamento del click (ms)",
|
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Aiuta con la precisione dei doppi clic",
|
|
||||||
"CLOCK_12H": "Orologio a 12 ore",
|
|
||||||
"CONTROLS": "Controlli",
|
|
||||||
"DELETE_ALL_CONFIGS": "Elimina configurazione",
|
|
||||||
"DELETE_ALL_CONFIGS_HELP": "Rimuovi tutti i file di configurazione da conf.d",
|
|
||||||
"DOUBLE_CURSOR_FIX": "Correzione doppio cursore",
|
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Abilita questa opzione se vedi 2 cursori",
|
|
||||||
"FEATURES": "Funzionalità",
|
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "Movimento del mouse al tocco del grilletto",
|
|
||||||
"HIDE_GRAB_HELP": "Nascondi l'aiuto per l'afferrare",
|
|
||||||
"HIDE_USERNAME": "Nascondi nome utente",
|
|
||||||
"INVERT_SCROLL_DIRECTION_X": "Inverti direzione dello scorrimento orizzontale",
|
|
||||||
"INVERT_SCROLL_DIRECTION_Y": "Inverti direzione dello scorrimento verticale",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK": "Click centrale del tasto",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK_HELP": "Modificatore da usare durante la digitazione\ncon laser viola",
|
|
||||||
"KEYBOARD_SOUND_ENABLED": "Suoni della tastiera",
|
|
||||||
"LEFT_HANDED_MOUSE": "Mouse per mancini",
|
|
||||||
"LEFT_HANDED_MOUSE_HELP": "Usalo se i pulsanti del mouse sono invertiti",
|
|
||||||
"LONG_PRESS_DURATION": "Durata pressione prolungata",
|
|
||||||
"LOOK_AND_FEEL": "Aspetto",
|
|
||||||
"MISC": "Varie",
|
|
||||||
"NOTIFICATIONS_ENABLED": "Abilita notifiche",
|
|
||||||
"NOTIFICATIONS_SOUND_ENABLED": "Suoni di notifica",
|
|
||||||
"OPAQUE_BACKGROUND": "Sfondo opaco",
|
|
||||||
"OPTION": {
|
|
||||||
"AUTO": "Automatico",
|
|
||||||
"AUTO_HELP": "Copia dello schermo tramite GPU se supportata,\naltrimenti tramite GPU PipeWire.",
|
|
||||||
"PIPEWIRE_HELP": "Acquisizione GPU veloce,\nstandard su tutti i desktop.",
|
|
||||||
"PW_FALLBACK_HELP": "Metodo lento con elevato utilizzo della CPU.\nProva in caso PipeWire GPU non funzioni",
|
|
||||||
"SCREENCOPY_GPU_HELP": "Veloce, senza popup di condivisione schermo.\nFunziona su: Hyprland, Niri, River, Sway",
|
|
||||||
"SCREENCOPY_HELP": "Lento, nessuna finestra pop-up per la condivisione dello schermo.\nFunziona su: Hyprland, Niri, River, Sway",
|
|
||||||
"NONE": "Nessuno",
|
|
||||||
"HMD_PINCH": "HMD + pizzico",
|
|
||||||
"EYE_PINCH": "Occhio + pizzico",
|
|
||||||
"EYE_ONLY": "Solo occhio",
|
|
||||||
"HMD_ONLY": "Solo HMD",
|
|
||||||
"NONE_INPUT_HELP": "Non emulare mouse e tastiera.\nNon sarà possibile interagire con gli schermi.",
|
|
||||||
"UINPUT": "Emulazione dispositivo",
|
|
||||||
"UINPUT_HELP": "Utilizza il modulo uinput per emulare un dispositivo.\nL'utente deve far parte del gruppo input.\nRisultato ottimale su quasi tutti i desktop.",
|
|
||||||
"WL_VIRTUAL": "Input virtuale Wayland",
|
|
||||||
"WL_VIRTUAL_HELP": "Invia eventi al compositor Wayland utilizzando\nzwlr_virtual_pointer e zwp_virtual_keyboard.\nFunziona in modo affidabile solo su alcuni desktop.\nNON funziona su KDE, GNOME o COSMIC."
|
|
||||||
},
|
|
||||||
"POINTER_LERP_FACTOR": "Smussamento puntatore",
|
|
||||||
"RESTART_SOFTWARE": "Riavvia il software",
|
|
||||||
"RESTART_SOFTWARE_HELP": "Applica impostazioni che richiedono un riavvio",
|
|
||||||
"ROUND_MULTIPLIER": "Arrotondamento bordi UI",
|
|
||||||
"SCREEN_RENDER_DOWN": "Rendering dello schermo a risoluzione inferiore",
|
|
||||||
"SCREEN_RENDER_DOWN_HELP": "Aiuta a ridurre l'aliasing su schermi ad alta risoluzione",
|
|
||||||
"SCROLL_SPEED": "Velocità di scorrimento",
|
|
||||||
"SETS_ON_WATCH": "Set sul Watch",
|
|
||||||
"SPACE_DRAG_MULTIPLIER": "Moltiplicatore space-drag",
|
|
||||||
"SPACE_DRAG_UNLOCKED": "Consenti lo space-drag su tutti gli assi",
|
|
||||||
"SPACE_ROTATE_UNLOCKED": "Consenti la rotazione dello spazio su tutti gli assi",
|
|
||||||
"TROUBLESHOOTING": "Risoluzione dei problemi",
|
|
||||||
"UPRIGHT_SCREEN_FIX": "Correzione schermo verticale",
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Corregge schermi verticali su alcuni desktop",
|
|
||||||
"USE_PASSTHROUGH": "Abilita passthrough",
|
|
||||||
"USE_PASSTHROUGH_HELP": "Consenti il passthrough se supportato dal runtime XR",
|
|
||||||
"USE_SKYBOX": "Abilita skybox",
|
|
||||||
"USE_SKYBOX_HELP": "Mostra uno skybox se non c'è un'app di scena o passthrough",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita",
|
|
||||||
"AUTOSTART_APPS": "App da avviare all'avvio",
|
|
||||||
"HANDSFREE_POINTER": "Modalità a mani libere",
|
|
||||||
"HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare.",
|
|
||||||
"UI_GRADIENT_INTENSITY": "Intensità gradiente dell'interfaccia utente",
|
|
||||||
"RESET_PLAYSPACE": "Ripristina playspace",
|
|
||||||
"RESET_PLAYSPACE_HELP": "Cancella l'offset dello spazio di gioco.",
|
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION": "Blocca le pose durante l'interazione con la tastiera",
|
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Impedisce al gioco di ricevere pose quando la tastiera è evidenziata e 'Blocca input di gioco' è abilitato",
|
|
||||||
"LANGUAGE": "Lingua",
|
|
||||||
"REQUIRES_RESTART": "Richiede riavvio",
|
|
||||||
"GRID_OPACITY": "Opacità della griglia del pavimento",
|
|
||||||
"GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skybox è abilitato",
|
|
||||||
"BROWSE_ONLINE_CATALOG": "Sfoglia catalogo online...",
|
|
||||||
"BROWSE_SKYMAPS": "Sfoglia skymap",
|
|
||||||
"COLOR_KEYING": "Keying del colore",
|
|
||||||
"NO_SKYMAPS_FOUND": "Nessuna skymap trovata",
|
|
||||||
"SELECT_VARIANT": "Seleziona variante",
|
|
||||||
"SHOW_WELCOME_SCREEN": "Mostra schermata di benvenuto",
|
|
||||||
"SKYBOX": "Skybox",
|
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "Questa skymap è già stata scaricata. Seleziona l'azione desiderata.",
|
|
||||||
"WATCH_VIEW_ANGLE": "Angoli di visualizzazione Watch",
|
|
||||||
"WATCH_VIEW_ANGLE_HELP": "Controlla come l'orologio sfuma",
|
|
||||||
"BINDINGS": {
|
"BINDINGS": {
|
||||||
"COMP": {
|
"COMP": {
|
||||||
"CLICK": "Clic",
|
"CLICK": "Clic",
|
||||||
|
|
@ -137,85 +58,204 @@
|
||||||
},
|
},
|
||||||
"TYPE": {
|
"TYPE": {
|
||||||
"BUMPER": "Bumper",
|
"BUMPER": "Bumper",
|
||||||
"DPAD_UP": "D-pad su",
|
"DPAD_UP": "D-pad Su",
|
||||||
"DPAD_DOWN": "D-pad Giù",
|
"DPAD_DOWN": "D-pad Giù",
|
||||||
"DPAD_LEFT": "D-pad Sinistra",
|
"DPAD_LEFT": "D-pad Sinistra",
|
||||||
"DPAD_RIGHT": "D-pad Destra",
|
"DPAD_RIGHT": "D-pad Destra",
|
||||||
"JOYSTICK": "Joystick",
|
"JOYSTICK": "Joystick",
|
||||||
"MENU": "Menu",
|
"MENU": "Menu",
|
||||||
"SHOULDER": "Spalla",
|
"SHOULDER": "Shoulder",
|
||||||
"SQUEEZE": "Grip",
|
"SQUEEZE": "Impugnatura",
|
||||||
"SYSTEM": "Sistema",
|
"SYSTEM": "Sistema",
|
||||||
"THUMBREST": "Appoggio del pollice",
|
"THUMBREST": "Appoggio pollice",
|
||||||
"THUMBSTICK": "Thumbstick",
|
"THUMBSTICK": "Thumbstick",
|
||||||
"TRACKPAD": "Trackpad",
|
"TRACKPAD": "Trackpad",
|
||||||
"TRIGGER": "Grilletto",
|
"TRIGGER": "Trigger",
|
||||||
"VIEW": "Visualizza"
|
"VIEW": "Vista"
|
||||||
},
|
},
|
||||||
"CLICK": {
|
"CLICK": {
|
||||||
"ANY": "Qualsiasi",
|
"ANY": "Qualsiasi",
|
||||||
"DOUBLE": "Doppio tocco",
|
"DOUBLE": "Doppio tocco",
|
||||||
"TRIPLE": "Triplo tocco",
|
"TRIPLE": "Triplo tocco",
|
||||||
"TYPE": "Numero di tocchi"
|
"TYPE": "Numero di tap"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"CLICK": "Click*",
|
"CLICK": "Clic*",
|
||||||
"GRAB": "Afferra*",
|
"GRAB": "Afferra*",
|
||||||
"ALT_CLICK": "Esecuzione shell personalizzata (imposta alt_click nella configurazione)",
|
"ALT_CLICK": "Exec shell personalizzato (imposta alt_click nel config)",
|
||||||
"SHOW_HIDE": "Mostra, nascondi, recentra*",
|
"SHOW_HIDE": "Mostra, nascondi, ricentra*",
|
||||||
"TOGGLE_DASHBOARD": "Attiva/disattiva dashboard",
|
"TOGGLE_DASHBOARD": "Attiva/disattiva dashboard",
|
||||||
"SPACE_DRAG": "Trascinamento playspace",
|
"SPACE_DRAG": "Trascinamento Playspace",
|
||||||
"SPACE_ROTATE": "Rotazione playspace",
|
"SPACE_ROTATE": "Rotazione Playspace",
|
||||||
"SPACE_RESET": "Reset playspace",
|
"SPACE_RESET": "Reset playspace",
|
||||||
"CLICK_MODIFIER_RIGHT": "Modificatore click destro",
|
"CLICK_MODIFIER_RIGHT": "Modificatore click destro",
|
||||||
"CLICK_MODIFIER_MIDDLE": "Modificatore click centrale",
|
"CLICK_MODIFIER_MIDDLE": "Modificatore click centrale",
|
||||||
"MOVE_MOUSE": "Muovi mouse (se disattivato di default)",
|
"MOVE_MOUSE": "Sposta mouse (se disattivato per impostazione predefinita)",
|
||||||
"SCROLL": "Scorrimento*"
|
"SCROLL": "Scorri*"
|
||||||
},
|
},
|
||||||
"LEFT": "Sinistra",
|
"LEFT": "Sinistra",
|
||||||
"RIGHT": "Destra",
|
"RIGHT": "Destro",
|
||||||
"COMPONENT": "Tipo di attivazione",
|
"COMPONENT": "Tipo di attuazione",
|
||||||
"SUBPATH": "Controllo di attivazione",
|
"SUBPATH": "Comando di attivazione",
|
||||||
"THRESHOLD": "Attiva quando sopra il valore superiore\nDisattiva quando sotto il valore inferiore"
|
"THRESHOLD": "Attiva sopra il valore superiore\nDisattiva sotto il valore inferiore"
|
||||||
},
|
},
|
||||||
"ENABLED": "Abilitato",
|
"BROWSE_ONLINE_CATALOG": "Sfoglia catalogo online...",
|
||||||
|
"BROWSE_SKYMAPS": "Sfoglia skymap",
|
||||||
|
"CAPTURE_METHOD": "Metodo di cattura schermo",
|
||||||
|
"CAPTURE_METHOD_HELP": "Prova a cambiarlo se riscontri\nschermi neri o glitch",
|
||||||
|
"COLOR_KEYING": "Chroma key",
|
||||||
|
"COLOR_PALETTE": "Tavolozza colori",
|
||||||
|
"COLOR_PALETTE_HELP": "Clicca per sfogliare le tavolozze dei colori.\nPer crearne di personalizzate, visita il sito web!",
|
||||||
|
"COLOR_PALETTES": "Tavolozze colori",
|
||||||
|
"COLOR_PALETTE_CURRENT": "Tema attualmente attivo.",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Aggiungi il tuo tema personalizzato!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Clicca per aprire il manuale web.",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS": "Svuota token PipeWire",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "Chiedi la selezione dello schermo al prossimo avvio",
|
||||||
|
"CLEAR_SAVED_STATE": "Ripristina stato salvato",
|
||||||
|
"CLEAR_SAVED_STATE_HELP": "Resetta set e posizioni degli overlay",
|
||||||
|
"CLICK_FREEZE_TIME_MS": "Tempo di freeze del click (ms)",
|
||||||
|
"CLICK_FREEZE_TIME_MS_HELP": "Aiuta la precisione del doppio clic",
|
||||||
|
"CLOCK_12H": "Orologio a 12 ore",
|
||||||
|
"CONTROLS": "Controlli",
|
||||||
|
"DELETE_ALL_CONFIGS": "Razzera configurazione",
|
||||||
|
"DELETE_ALL_CONFIGS_HELP": "Rimuovi tutti i file di configurazione da conf.d",
|
||||||
|
"DOUBLE_CURSOR_FIX": "Correzione doppio cursore",
|
||||||
|
"DOUBLE_CURSOR_FIX_HELP": "Attivalo se vedi 2 cursori",
|
||||||
|
"DEFAULT_OVERLAY_SCALE": "Dimensione overlay predefinita",
|
||||||
|
"DEFAULT_OVERLAY_SCALE_HELP": "Fai apparire i nuovi overlay a questa scala.",
|
||||||
|
"DEFAULT_CURVATURE": "Curvatura predefinita overlay",
|
||||||
|
"DEFAULT_OPACITY": "Opacità predefinita overlay",
|
||||||
|
"DEFAULT_POSITIONING": "Posizionamento overlay predefinito",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "Si applica solo ai nuovi overlay",
|
||||||
|
"ENABLED": "Attivo",
|
||||||
|
"FEATURES": "Funzionalità",
|
||||||
|
"FOCUS_FOLLOWS_MOUSE_MODE": "Muovi mouse al tocco del trigger",
|
||||||
|
"HANDSFREE_POINTER": "Modalità mani libere",
|
||||||
|
"HANDSFREE_POINTER_HELP": "Input da usare quando i controller \ndi movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare.",
|
||||||
|
"HANDSFREE_ALT_TAB": "Mirino commutatore app",
|
||||||
|
"HANDSFREE_ALT_TAB_HELP": "Tieni premuto Super+X, punta alla finestra desiderata e rilascia per cambiare focus.",
|
||||||
|
"HIDE_GRAB_HELP": "Nascondi guida alla presa",
|
||||||
|
"HIDE_USERNAME": "Nascondi nome utente",
|
||||||
"INPUT_EMULATION_METHOD": "Metodo di emulazione input",
|
"INPUT_EMULATION_METHOD": "Metodo di emulazione input",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "Prova a cambiare questa impostazione nel caso in cui l'input del mouse o \ndella tastiera non venga registrato.",
|
"INPUT_EMULATION_METHOD_HELP": "Prova a cambiarlo se l'input del mouse o\ndella tastiera non viene registrato.",
|
||||||
"INPUT_PROFILES": "Cambia i binding di input",
|
"INPUT_CAPTURE_METHOD": "Metodo di acquisizione input",
|
||||||
"INPUT_PROFILES_HELP": "Binding di input del controller OpenXR",
|
"INPUT_CAPTURE_METHOD_HELP": "Permette di usare le periferiche fisiche all'interno di WayVR.\n Super+Z: Passa l'input tra WayVR e il desktop reale\n Super+X: Passa tra le app di WayVR",
|
||||||
|
"INPUT_PROFILES": "Cambia assegnazione tasti",
|
||||||
|
"INPUT_PROFILES_HELP": "Binding degli input del controller OpenXR",
|
||||||
|
"INVERT_SCROLL_DIRECTION_X": "Inverti direzione scorrimento orizzontale",
|
||||||
|
"INVERT_SCROLL_DIRECTION_Y": "Inverti direzione scorrimento verticale",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK": "Tasto centrale tastiera",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK_HELP": "Tasto modificatore da usare quando si scrive\ncon il laser viola",
|
||||||
|
"KEYBOARD_SOUND_ENABLED": "Suoni tastiera",
|
||||||
|
"LANGUAGE": "Lingua",
|
||||||
|
"LEFT_HANDED_MOUSE": "Mouse per mancini",
|
||||||
|
"LEFT_HANDED_MOUSE_HELP": "Usalo se i tasti del mouse sono invertiti",
|
||||||
|
"LONG_PRESS_DURATION": "Durata pressione lunga",
|
||||||
|
"LOOK_AND_FEEL": "Aspetto e stile",
|
||||||
|
"MISC": "Varie",
|
||||||
|
"NOTIFICATIONS_ENABLED": "Attiva notifiche",
|
||||||
|
"NOTIFICATIONS_SOUND_ENABLED": "Suoni di notifica",
|
||||||
"NOT_SUPPORTED": "Non supportato",
|
"NOT_SUPPORTED": "Non supportato",
|
||||||
"ENABLE_WATCH": "Abilita watch",
|
"NO_SKYMAPS_FOUND": "Nessun skymap trovato",
|
||||||
"SPACE_DRAG": "Space drag",
|
"OPAQUE_BACKGROUND": "Sfondo opaco",
|
||||||
"SPACE_GRAVITY_DAMPING": "Smorzamento",
|
"OPTION": {
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "Resistenza artificiale per rallentare il movimento. 0.1 - alta resistenza, 1.0 - nessuna resistenza",
|
"ANCHORED_HELP": "Si muove con il marker centrale. Consigliato.",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH": "Forza del lancio",
|
"FLOATING_HELP": "Si muove indipendentemente, si ricentra.\nFacile da perdere di vista; non consigliato.",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Moltiplicatore dell'intensità della forza di lancio gravitazionale dopo lo space-drag.\n0.0 - nessun movimento, 2.0 - intensità doppia",
|
"STATIC_HELP": "Resta fisso rispetto al mondo.",
|
||||||
"SPACE_GRAVITY_GRAVITY": "Gravità",
|
"AUTO": "Automatico",
|
||||||
"SPACE_GRAVITY_GRAVITY_HELP": "Quantità di forza verso il basso. 0.0 - nessuna gravità",
|
"AUTO_HELP": "ScreenCopy GPU se supportata,\naltrimenti PipeWire GPU.",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION": "Attrito del terreno",
|
"EYE_ONLY": "Laser oculare",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Quantità di attrito che ti rallenta se tocchi il suolo.\n0.0 - nessuna frizione (proprio come sul ghiaccio), 1.0 - superficie ruvida",
|
"EYE_PINCH": "Occhio + pinch",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altezza del pavimento",
|
"HMD_ONLY": "Laser HMD",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posizione Y in cui si trova il pavimento. La gravità si ferma quando raggiungi questa altezza.",
|
"HMD_PINCH": "HMD + pinch",
|
||||||
"SAVE": "Salva",
|
"NONE": "Nessuno",
|
||||||
"CANCEL": "Annulla",
|
"NONE_INPUT_HELP": "Non emulare mouse e tastiera.\nNon sarà possibile interagire con gli schermi.",
|
||||||
"WHISPER": {
|
"NONE_INPUT_CAPTURE_HELP": "Non catturare mouse e tastiera.\nNon sarà possibile usare il mouse o la\ntastiera fisica nelle app lanciate in WayVR.",
|
||||||
"NEED_TO_DOWNLOAD_MODEL": "Il modello selezionato deve essere scaricato.\nVuoi scaricarlo adesso?",
|
"PIPEWIRE_HELP": "Cattura GPU rapida,\nstandard su tutti i desktop.",
|
||||||
"REMOVE_UNUSED_MODELS": "Stai disattivando la funzione di sintesi vocale.\nDesideri rimuovere i modelli Whisper scaricati per liberare spazio?"
|
"PW_FALLBACK_HELP": "Metodo lento con elevato utilizzo della CPU.\nProva se PipeWire GPU non funziona",
|
||||||
|
"SCREENCOPY_GPU_HELP": "Veloce, senza popup di condivisione schermo.\nFunziona con: Hyprland, Niri, River, Sway",
|
||||||
|
"SCREENCOPY_HELP": "Lenta, senza popup di condivisione schermo.\nFunziona su: Hyprland, Niri, River, Sway",
|
||||||
|
"UINPUT": "Emulazione dispositivo",
|
||||||
|
"UINPUT_HELP": "Utilizza il modulo uinput per emulare un dispositivo.\nFunziona bene sulla maggior parte dei desktop.",
|
||||||
|
"EVDEV_HELP": "Cattura i dispositivi di input per l'uso esclusivo.\nL'utente deve appartenere al gruppo 'input'.",
|
||||||
|
"WL_VIRTUAL": "Input virtuale Wayland",
|
||||||
|
"WL_VIRTUAL_HELP": "Invia eventi al compositor Wayland usando\nzwlr_virtual_pointer e zwp_virtual_keyboard.\nFunziona in modo affidabile solo su alcuni desktop.\nNON funziona su KDE, GNOME o COSMIC."
|
||||||
},
|
},
|
||||||
"WHISPER_MODEL": "Modello di sintesi vocale (speech-to-text)",
|
"POINTER_ACCELERATION": "Accelerazione mouse",
|
||||||
"WHISPER_MODEL_HELP": "Modello Whisper da utilizzare.\nI modelli più grandi producono risultati\npiù accurati, ma consumano più VRAM."
|
"POINTER_ACCELERATION_HELP": "On: Accelerazione mouse adattiva\nOff: Velocità costante",
|
||||||
|
"POINTER_LERP_FACTOR": "Smorzamento puntatore",
|
||||||
|
"POINTER_SPEED": "Velocità mouse",
|
||||||
|
"REQUIRES_RESTART": "Richiede riavvio",
|
||||||
|
"RESET_PLAYSPACE": "Resetta playspace",
|
||||||
|
"RESET_PLAYSPACE_HELP": "Rimuovi l'offset dello spazio del Playspace.",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "Salva centro playspace",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "Usa il playspace corrente per il comando di reset del playspace.",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "Resetta centro playspace",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "Rimuovi il centro del playspace impostato precedentemente.",
|
||||||
|
"RESTART_SOFTWARE": "Riavvia software",
|
||||||
|
"RESTART_SOFTWARE_HELP": "Applica le impostazioni che richiedono il riavvio",
|
||||||
|
"ROUND_MULTIPLIER": "Arrotondamento bordi UI",
|
||||||
|
"SCREEN_RENDER_DOWN": "Rendering schermo a risoluzione inferiore",
|
||||||
|
"SCREEN_RENDER_DOWN_HELP": "Riduce l'effetto aliasing sugli schermi ad alta risoluzione",
|
||||||
|
"SCROLL_SPEED": "Velocità scorrimento",
|
||||||
|
"SELECT_VARIANT": "Seleziona variante",
|
||||||
|
"SNAP_ANGLE_DEG": "Angolo di snap beccheggio e rollio finestre",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "Le finestre afferrate si allineano a questo angolo sugli assi di beccheggio e rollio.",
|
||||||
|
"ENABLE_WATCH": "Attiva orologio",
|
||||||
|
"SETS_ON_WATCH": "Set sull'orologio",
|
||||||
|
"SHOW_WELCOME_SCREEN": "Mostra schermata di benvenuto",
|
||||||
|
"SKYBOX": "Skymap",
|
||||||
|
"SKYMAP_ALREADY_DOWNLOADED": "Questo skymap è già stato scaricato. Seleziona l'azione desiderata.",
|
||||||
|
"SPACE_DRAG": "Playspace",
|
||||||
|
"SPACE_DRAG_MULTIPLIER": "Moltiplicatore Space-drag",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "Lascia gli overlay durante lo spostamento del playspace",
|
||||||
|
"SPACE_DRAG_UNLOCKED": "Permetti space-drag su tutti gli assi",
|
||||||
|
"SPACE_GRAVITY_DAMPING": "Smorzamento",
|
||||||
|
"SPACE_GRAVITY_DAMPING_HELP": "Attrito artificiale per rallentare il movimento. 0,1 - attrito elevato, 1,0 - nessun attrito",
|
||||||
|
"SPACE_GRAVITY_FLING_STRENGTH": "Forza del lancio",
|
||||||
|
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Moltiplicatore dell'intensità della spinta gravitazionale dopo lo space-drag.\n0.0 - nessun movimento, 2.0 - intensità doppia",
|
||||||
|
"SPACE_GRAVITY_GRAVITY": "Gravità",
|
||||||
|
"SPACE_GRAVITY_GRAVITY_HELP": "Forza verso il basso. 0.0 - assenza di gravità",
|
||||||
|
"SPACE_GRAVITY_GROUND_FRICTION": "Attrito al suolo",
|
||||||
|
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Quantità di attrito che ti rallenta quando tocchi terra.\n0.0 - nessun attrito (come sul ghiaccio), 1.0 - superficie ruvida",
|
||||||
|
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altezza pavimento",
|
||||||
|
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posizione Y del pavimento. La gravità si interrompe quando raggiungi questa altezza.",
|
||||||
|
"SPACE_ROTATE_UNLOCKED": "Consenti rotazione del playspace su tutti gli assi",
|
||||||
|
"TROUBLESHOOTING": "Risoluzione problemi",
|
||||||
|
"UI_GRADIENT_INTENSITY": "Intensità gradiente UI",
|
||||||
|
"UPRIGHT_SCREEN_FIX": "Correzione orientamento schermo",
|
||||||
|
"UPRIGHT_SCREEN_FIX_HELP": "Risolve il problema degli schermi verticali su alcuni desktop",
|
||||||
|
"USE_PASSTHROUGH": "Abilita passthrough",
|
||||||
|
"USE_PASSTHROUGH_HELP": "Consenti il passthrough se supportato dal runtime XR",
|
||||||
|
"USE_SKYBOX": "Mostra skymap",
|
||||||
|
"USE_SKYBOX_HELP": "Mostra una skymap se non c'è un'app di scena o il passthrough",
|
||||||
|
"WATCH_VIEW_ANGLE": "Angoli di visualizzazione orologio",
|
||||||
|
"WATCH_VIEW_ANGLE_HELP": "Controlla come scompare l'orologio",
|
||||||
|
"WHISPER": {
|
||||||
|
"NEED_TO_DOWNLOAD_MODEL": "Il modello selezionato deve essere scaricato.\nScaricarlo ora?",
|
||||||
|
"REMOVE_UNUSED_MODELS": "Stai disattivando la funzione di riconoscimento vocale.\nVuoi rimuovere i modelli Whisper scaricati per liberare spazio?"
|
||||||
|
},
|
||||||
|
"WHISPER_MODEL": "Modello speech-to-text",
|
||||||
|
"WHISPER_MODEL_HELP": "Modello Whisper da utilizzare.\nModelli più grandi offrono risultati\npiù precisi, ma consumano più VRAM.",
|
||||||
|
"GRID_OPACITY": "Opacità griglia pavimento",
|
||||||
|
"GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skymap è attivo",
|
||||||
|
"XWAYLAND_BY_DEFAULT": "Avvia le app in modalità compatibilità per impostazione predefinita",
|
||||||
|
"SAVE": "Salva",
|
||||||
|
"CANCEL": "Annulla"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
"APPLICATION_LAUNCHER": "Avvio applicazioni",
|
||||||
"APPLICATION_STARTED": "Applicazione avviata",
|
"APPLICATION_STARTED": "Applicazione avviata",
|
||||||
"APPLICATIONS": "Applicazioni",
|
"APPLICATIONS": "Applicazioni",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
"AUTO_SWITCH_TO_VR_AUDIO": "Passa automaticamente all'audio VR",
|
"AUTO_SWITCH_TO_VR_AUDIO": "Passa automaticamente all'audio VR",
|
||||||
"CARDS": "Schede",
|
"CARDS": "Schede",
|
||||||
"FAILED_TO_SWITCH_MICROPHONE": "Impossibile cambiare microfono",
|
"FAILED_TO_SWITCH_MICROPHONE": "Errore nel cambio microfono",
|
||||||
"MICROPHONE_SET_SUCCESSFULLY": "Microfono impostato con successo",
|
"MICROPHONE_SET_SUCCESSFULLY": "Microfono impostato correttamente",
|
||||||
"MICROPHONES": "Microfoni",
|
"MICROPHONES": "Microfoni",
|
||||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Nessun microfono VR trovato. Attivalo manualmente.",
|
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Nessun microfono VR trovato. Selezionalo manualmente.",
|
||||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Nessun altoparlante VR trovato. Selezionali manualmente.",
|
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Altoparlanti VR non trovati. Selezionali manualmente.",
|
||||||
"SELECT_AUDIO_CARD_PROFILE": "Seleziona profilo scheda audio",
|
"SELECT_AUDIO_CARD_PROFILE": "Seleziona profilo scheda audio",
|
||||||
"SETTINGS": "Impostazioni audio",
|
"SETTINGS": "Impostazioni audio",
|
||||||
"SPEAKERS": "Altoparlanti",
|
"SPEAKERS": "Altoparlanti",
|
||||||
|
|
@ -223,78 +263,87 @@
|
||||||
"VOLUME": "Volume"
|
"VOLUME": "Volume"
|
||||||
},
|
},
|
||||||
"CLOSE_WINDOW": "Chiudi finestra",
|
"CLOSE_WINDOW": "Chiudi finestra",
|
||||||
"DISPLAY_BRIGHTNESS": "Luminosità display",
|
"CREATION_DATE": "Data di creazione",
|
||||||
"FAILED_TO_LAUNCH_APPLICATION": "Impossibile avviare l'applicazione:",
|
"DEBUG_INFO": "Info debug",
|
||||||
"GAME_LAUNCHED": "Gioco lanciato",
|
"DISPLAY_BRIGHTNESS": "Luminosità schermo",
|
||||||
|
"DONATE": {
|
||||||
|
"SUPPORT_US": "Sostienici",
|
||||||
|
"DESCRIPTION": "Siamo un piccolo team di 2 sviluppatori che realizza WayVR nel tempo libero. Se ti piace usare questo software, considera di supportarci: ogni donazione ci aiuta a continuare.",
|
||||||
|
"THANK_YOU_WAYVR": "Grazie dal team di WayVR!",
|
||||||
|
"BUTTON_TOOLTIP": "Donazione tramite Open Collective",
|
||||||
|
"CURRENT_SUPPORTERS": "Supporter attuali",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Supportato da {USER}|Grazie speciali a {USER}|Sponsorizzato da {USER}|Contributo di {USER}|Sostenuto da membri come {USER}|Reso possibile da {USER}|Sostenuto da {USER}|Grazie a {USER}|Alimentato da {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "Caffè offerto da {USER}|Energia pura grazie a {USER}|Un grande applauso a {USER}!|Ci tiene in piedi: {USER}|Ci aiuta a crescere: {USER}|Mantiene i server accesi: {USER}|Con immensa gratitudine a {USER}|Spinto dalla forza di {USER}|Supportato da amici come {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Supportato da leggende come {USER}|Caffeina fornita da {USER}|Una vera leggenda: {USER}|Il nostro eroe del giorno: {USER}|Una superstar assoluta: {USER}|Paga la bolletta della luce: {USER}|Il motore della nostra creatività: {USER}|Il navigatore del nostro percorso: {USER}|Convertitore caffeina-codice fornito da {USER}|Mantiene la produzione stabile: {USER}|L'unico e inimitabile: {USER}|Maestro dei buffer dmabuf: {USER}"
|
||||||
|
},
|
||||||
|
"DOWNLOAD": "Scarica",
|
||||||
|
"DOWNLOADER": "Download",
|
||||||
|
"WELCOME": {
|
||||||
|
"ALL_SET": "Sei pronto!",
|
||||||
|
"BASICS": "Questi concetti base ti permetteranno di usare WayVR con facilità.",
|
||||||
|
"CENTER_MARKER": "Il marker centrale è ciò che apparirà davanti a te durante il ricentramento. Posiziona gli overlay intorno ad esso!",
|
||||||
|
"DOUBLE_PRESS_TO_TOGGLE": "Premi due volte B (su Index) o Y (su Meta) per mostrare, ricentrare o nascondere il tuo Set. Prova ora.",
|
||||||
|
"FEATURES_DOCUMENTATION": "Ci sono molte altre funzioni che vale la pena personalizzare. Per maggiori informazioni, consulta la documentazione su",
|
||||||
|
"FINISH_TUTORIAL": "Completa tutorial",
|
||||||
|
"GRAB_BOTH_HANDS": "Afferra con entrambe le mani se vuoi spostare un overlay specifico del tuo set.",
|
||||||
|
"GRAB_ONE_HAND": "Afferra con una mano per spostare il set.",
|
||||||
|
"GREETING": "Ciao!",
|
||||||
|
"GUIDE_INTRO": "Ti guidiamo attraverso i primi passi.",
|
||||||
|
"LASER_COLORS": "Colori del laser",
|
||||||
|
"LASER_FUNCTIONALITY": "Gran parte delle funzionalità di WayVR dipende dal colore del laser usato per interagire con gli elementi dell'interfaccia. Non serve premere i pulsanti, basta toccarli!",
|
||||||
|
"LAST_PAGE_INFO": "Questo tutorial smetterà di apparire una volta raggiunta l'ultima pagina.",
|
||||||
|
"LOOK_AT_LEFT_WRIST": "Guarda il tuo polso sinistro. Quello è il tuo orologio.",
|
||||||
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Modalità click centrale: laser viola",
|
||||||
|
"MOVING_YOUR_SET": "Spostare il set",
|
||||||
|
"NEXT_BUTTON": "Premi Avanti qui sotto per iniziare.",
|
||||||
|
"REGULAR_MODE_BLUE_LASER": "Modalità standard: laser blu",
|
||||||
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Riposiziona questa finestra usando il tasto grip del controller.",
|
||||||
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "Modalità tasto destro: Laser arancione",
|
||||||
|
"THANKS_FOR_INSTALLING": "Grazie per aver installato WayVR!",
|
||||||
|
"WATCH": "Orologio",
|
||||||
|
"WORKING_SET": "Set attivo"
|
||||||
|
},
|
||||||
|
"DOWNLOAD_AGAIN": "Scarica di nuovo",
|
||||||
|
"DOWNLOADING_FILE": "Download file in corso...",
|
||||||
|
"FAILED_TO_LAUNCH_APPLICATION": "Errore nel lancio dell'applicazione:",
|
||||||
|
"GAME_LAUNCHED": "Gioco avviato",
|
||||||
"GAME_LIST": {
|
"GAME_LIST": {
|
||||||
"NO_GAMES_FOUND": "Nessun gioco trovato",
|
"NO_GAMES_FOUND": "Nessun gioco trovato",
|
||||||
"RUNNING_GAMES_LIST": "Lista dei giochi in esecuzione"
|
"RUNNING_GAMES_LIST": "Lista giochi in esecuzione"
|
||||||
},
|
},
|
||||||
"GAMES": "Giochi",
|
"GAMES": "Giochi",
|
||||||
"GENERAL_SETTINGS": "Impostazioni generali",
|
"GENERAL_SETTINGS": "Impostazioni generali",
|
||||||
|
"GETTING_STARTED": "Inizia qui",
|
||||||
"HEIGHT": "Altezza",
|
"HEIGHT": "Altezza",
|
||||||
"HELLO": "Ciao!",
|
"HELLO": "Ciao!",
|
||||||
"HELLO_USER": "Ciao, {USER}!",
|
"HELLO_USER": "Ciao, {USER}!",
|
||||||
"HIDE": "Nascondi",
|
"HIDE": "Nascondi",
|
||||||
"HOME_SCREEN": "Home",
|
"HOME_SCREEN": "Home",
|
||||||
"MONADO_RUNTIME": "Runtime Monado",
|
"MODIFICATION_DATE": "Data modifica",
|
||||||
|
"MONADO_RUNTIME": "Runtime di Monado",
|
||||||
|
"LOADING": "Caricamento...",
|
||||||
"POPUP_ADD_DISPLAY": {
|
"POPUP_ADD_DISPLAY": {
|
||||||
"RESOLUTION": "Risoluzione"
|
"RESOLUTION": "Risoluzione"
|
||||||
},
|
},
|
||||||
|
"PROCESS": {
|
||||||
|
"FORCE_KILL": "Chiudi forzatamente",
|
||||||
|
"STOP": "Ferma"
|
||||||
|
},
|
||||||
|
"PROCESS_LIST": "Lista processi",
|
||||||
|
"REFRESH": "Aggiorna",
|
||||||
"REMOVE": "Rimuovi",
|
"REMOVE": "Rimuovi",
|
||||||
|
"APPLY": "Applica",
|
||||||
|
"RELOAD_FROM_DISK": "Ricarica dal disco",
|
||||||
"SETTINGS": "Impostazioni",
|
"SETTINGS": "Impostazioni",
|
||||||
"SHOW": "Mostra",
|
"SHOW": "Mostra",
|
||||||
"TERMINATE_PROCESS": "Termina processo",
|
|
||||||
"WIDTH": "Larghezza",
|
|
||||||
"PROCESS_LIST": "Elenco processi",
|
|
||||||
"REFRESH": "Aggiorna",
|
|
||||||
"PROCESS": {
|
|
||||||
"STOP": "Interrompi",
|
|
||||||
"FORCE_KILL": "Uccidi forzatamente"
|
|
||||||
},
|
|
||||||
"DEBUG_INFO": "Informazioni di debug",
|
|
||||||
"CREATION_DATE": "Data di creazione",
|
|
||||||
"DOWNLOADER": "Downloader",
|
|
||||||
"DOWNLOAD_AGAIN": "Scarica di nuovo",
|
|
||||||
"DOWNLOADING_FILE": "Download del file in corso...",
|
|
||||||
"GETTING_STARTED": "Inizio rapido",
|
|
||||||
"MODIFICATION_DATE": "Data di modifica",
|
|
||||||
"LOADING": "Caricamento...",
|
|
||||||
"APPLY": "Applica",
|
|
||||||
"RELOAD_FROM_DISK": "Ricarica da disco",
|
|
||||||
"TARGET_PATH": "Percorso di destinazione",
|
"TARGET_PATH": "Percorso di destinazione",
|
||||||
|
"TERMINATE_PROCESS": "Termina processo",
|
||||||
"VERSION": "Versione",
|
"VERSION": "Versione",
|
||||||
"DONATE": {
|
"WIDTH": "Larghezza",
|
||||||
"SUPPORT_US": "Sostienici",
|
"PINNED_APPS": "Applicazioni fissate",
|
||||||
"DESCRIPTION": "Siamo un piccolo team di 2 sviluppatori che crea WayVR nel tempo libero. Se ti piace usare questo software, considera di supportarci: ogni donazione ci aiuta a continuare.",
|
"SAVED_TO_FAVOURITES": "Salvato nelle applicazioni fissate",
|
||||||
"BUTTON_TOOLTIP": "Dona tramite Open Collective",
|
"ADD_TO_FAVOURITES": "Aggiungi alle applicazioni fissate",
|
||||||
"CURRENT_SUPPORTERS": "Sostenitori attuali",
|
"ADD_TO_FAVOURITES_HINT": "Salva il preset e fissalo al cassetto delle app",
|
||||||
"THANK_YOU_WAYVR": "Grazie dal team WayVR!"
|
"REMOVE_FROM_FAVOURITES": "Rimuovi dalle app fissate",
|
||||||
},
|
"EMPTY": "Vuoto"
|
||||||
"WELCOME": {
|
|
||||||
"ALL_SET": "Sei pronto!",
|
|
||||||
"BASICS": "Queste nozioni di base ti permetteranno di iniziare a usare WayVR con facilità.",
|
|
||||||
"CENTER_MARKER": "Il marker centrale determina il centro del tuo set.",
|
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "Premi due volte B (su Index) o Y (su Meta) per attivare/disattivare la visibilità del tuo workspace. Provalo subito.",
|
|
||||||
"FEATURES_DOCUMENTATION": "Ci sono molte altre funzioni che vale la pena personalizzare. Per ulteriori informazioni, consulta la documentazione all'indirizzo",
|
|
||||||
"FINISH_TUTORIAL": "Termina tutorial",
|
|
||||||
"GRAB_BOTH_HANDS": "Afferralo con entrambe le mani se vuoi spostare un overlay specifico nel tuo set.",
|
|
||||||
"GRAB_ONE_HAND": "Afferralo con una mano per muovere il tuo set.",
|
|
||||||
"GREETING": "Ciao!",
|
|
||||||
"GUIDE_INTRO": "Lascia che ti guidiamo nei tuoi primi passi.",
|
|
||||||
"LASER_COLORS": "Colori Laser",
|
|
||||||
"LASER_FUNCTIONALITY": "Gran parte delle funzionalità in WayVR dipende dal colore del laser utilizzato per interagire con un elemento dell'interfaccia utente. Non è necessario premere questi pulsanti, basta toccarli!",
|
|
||||||
"LAST_PAGE_INFO": "Questo tutorial smetterà di apparire una volta raggiunta l'ultima pagina.",
|
|
||||||
"LOOK_AT_LEFT_WRIST": "Guarda il tuo polso sinistro. È il tuo watch.",
|
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Modalità click centrale: Laser viola",
|
|
||||||
"MOVING_YOUR_SET": "Spostamento del tuo set",
|
|
||||||
"NEXT_BUTTON": "Premi il pulsante \"Avanti\" qui sotto per iniziare.",
|
|
||||||
"REGULAR_MODE_BLUE_LASER": "— Modalità Standard: Laser blu",
|
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Riposiziona questa finestra usando l'azione grip del tuo controller.",
|
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Modalità tasto destro: Laser arancione",
|
|
||||||
"THANKS_FOR_INSTALLING": "Grazie per aver installato WayVR!",
|
|
||||||
"WATCH": "Watch",
|
|
||||||
"WORKING_SET": "Set di lavoro"
|
|
||||||
},
|
|
||||||
"DOWNLOAD": "Scarica"
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,300 +1,349 @@
|
||||||
{
|
{
|
||||||
"HOME_SCREEN": "ホーム",
|
"DEFINITIONS": {
|
||||||
"MONADO_RUNTIME": "「Monado」ランタイム",
|
"ANCHORED": "セット追従",
|
||||||
"APPLICATIONS": "アプリ",
|
"FLOATING": "フローティング",
|
||||||
"GAMES": "ゲーム",
|
"STATIC": "固定",
|
||||||
"SETTINGS": "設定",
|
"SET": "セット",
|
||||||
"HELLO_USER": "こんにちは、{USER}!",
|
"WATCH": "ウォッチ",
|
||||||
"GENERAL_SETTINGS": "全般設定",
|
"DASHBOARD": "ダッシュボード",
|
||||||
"APPLICATION_LAUNCHER": "アプリケーションランチャー",
|
"EDIT_MODE": "編集モード",
|
||||||
"APP_SETTINGS": {
|
"SETTINGS": "設定",
|
||||||
"HIDE_USERNAME": "ユーザー名を非表示",
|
"KEYBOARD": "キーボード",
|
||||||
"OPAQUE_BACKGROUND": "不透明な背景",
|
"TASKBAR": "タスクバー",
|
||||||
"LOOK_AND_FEEL": "外観",
|
|
||||||
"HIDE_GRAB_HELP": "グリップ動作中にのヘルプを非表示",
|
|
||||||
"ANIMATION_SPEED": "UIアニメーション速度",
|
|
||||||
"ROUND_MULTIPLIER": "UI の丸み",
|
|
||||||
"USE_SKYBOX": "スカイボックスを有効",
|
|
||||||
"USE_PASSTHROUGH": "パススルーを有効",
|
|
||||||
"CLOCK_12H": "12時間制",
|
|
||||||
"FEATURES": "機能",
|
"FEATURES": "機能",
|
||||||
"NOTIFICATIONS_ENABLED": "通知を有効にする",
|
"OVERLAY": "オーバーレイ",
|
||||||
"NOTIFICATIONS_SOUND_ENABLED": "通知音",
|
"SKYMAP": "スカイマップ",
|
||||||
"KEYBOARD_SOUND_ENABLED": "キーボード音",
|
"PLAYSPACE": "プレイスペース",
|
||||||
"SPACE_DRAG_MULTIPLIER": "スペースドラッグ倍率",
|
"D_PAD": "十字キー"
|
||||||
"SPACE_DRAG_UNLOCKED": "全軸のスペースドラッグ",
|
},
|
||||||
"SPACE_ROTATE_UNLOCKED": "全軸のスペース回転",
|
"ACTIONS": {
|
||||||
"BLOCK_GAME_INPUT": "ゲームの入力をブロック",
|
"RECENTER_PLAYSPACE": "プレイスペースをリセンター"
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "入力ブロック時に監視を無視",
|
},
|
||||||
"CONTROLS": "コントロール",
|
"APP_LAUNCHER": {
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "トリガータッチでマウス移動",
|
"ASPECT": {
|
||||||
"LEFT_HANDED_MOUSE": "左利きマウス",
|
"SEMI_TALL": "やや縦長",
|
||||||
"ALLOW_SLIDING": "グリップ動作中にスティックを有効",
|
"SEMI_WIDE": "セミワイド",
|
||||||
"INVERT_SCROLL_DIRECTION_X": "水平スクロール方向を反転",
|
"SQUARE": "正方形",
|
||||||
"INVERT_SCROLL_DIRECTION_Y": "垂直スクロール方向を反転",
|
"TALL": "縦長",
|
||||||
"SCROLL_SPEED": "スクロール速度",
|
"WIDE": "ワイド"
|
||||||
"LONG_PRESS_DURATION": "長押し時間",
|
|
||||||
"POINTER_LERP_FACTOR": "ポインターのスムージング",
|
|
||||||
"CLICK_FREEZE_TIME_MS": "クリックで一時停止時間 (ms)",
|
|
||||||
"MISC": "その他",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "アプリ実行のデフォルトは互換モード",
|
|
||||||
"UPRIGHT_SCREEN_FIX": "画面の縦向き修正",
|
|
||||||
"DOUBLE_CURSOR_FIX": "ダブルカーソル修正",
|
|
||||||
"SCREEN_RENDER_DOWN": "画面の解像度を縮小",
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "一部のデスクトップで縦向きの画面を修正",
|
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "2つのカーソルが表示される場合は、これを有効にします",
|
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "ダブルクリックの精度向上に役立ちます",
|
|
||||||
"LEFT_HANDED_MOUSE_HELP": "マウスボタンが入れ替わっている場合に有効にします",
|
|
||||||
"BLOCK_GAME_INPUT_HELP": "オーバーレイ上にマウスカーソルがあるときに入力をブロックします",
|
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "ウォッチがホバーされているときは入力をブロックしない",
|
|
||||||
"USE_SKYBOX_HELP": "シーンアプリまたはパススルーがない場合にスカイボックスを表示します",
|
|
||||||
"USE_PASSTHROUGH_HELP": "XRランタイムがサポートしていれば、パススルーを有効にします",
|
|
||||||
"SCREEN_RENDER_DOWN_HELP": "高解像度スクリーンでのエイリアシングを軽減します",
|
|
||||||
"SETS_ON_WATCH": "ウォッチのセット",
|
|
||||||
"TROUBLESHOOTING": "トラブルシューティング",
|
|
||||||
"CLEAR_SAVED_STATE": "保存された状態をクリア",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "PipeWire トークンをクリア",
|
|
||||||
"DELETE_ALL_CONFIGS": "設定を消去",
|
|
||||||
"RESTART_SOFTWARE": "ソフトウェアを再起動",
|
|
||||||
"CLEAR_SAVED_STATE_HELP": "セットとオーバーレイの位置をリセット",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "次の起動時に画面選択のプロンプトを表示",
|
|
||||||
"DELETE_ALL_CONFIGS_HELP": "conf.d 内のすべての設定ファイルを削除",
|
|
||||||
"RESTART_SOFTWARE_HELP": "再起動が必要な設定を適用",
|
|
||||||
"CAPTURE_METHOD": "Waylandスクリーンキャプチャ",
|
|
||||||
"CAPTURE_METHOD_HELP": "画面が黒くなる、または乱れる場合は、\nこの設定を変更してみてください。",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK": "キーボードの中ボタンクリック",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK_HELP": "紫色のレーザーで入力する際の修飾キー",
|
|
||||||
"OPTION": {
|
|
||||||
"AUTO": "自動",
|
|
||||||
"AUTO_HELP": "サポートされている場合はScreenCopy GPU、\nそうでない場合はPipeWire GPU。",
|
|
||||||
"PIPEWIRE_HELP": "GPU高速キャプチャ。\nすべてのデスクトップで標準です。",
|
|
||||||
"PW_FALLBACK_HELP": "CPU使用量が多い低速な方法です。\nPipeWire GPUが動作しない場合に試してください。",
|
|
||||||
"SCREENCOPY_GPU_HELP": "高速で、スクリーン共有ポップアップはありません。\n動作する環境: Hyprland, Niri, River, Sway",
|
|
||||||
"SCREENCOPY_HELP": "遅延あり、画面共有ポップアップなし。\n動作する環境: Hyprland, Niri, River, Sway",
|
|
||||||
"NONE": "なし",
|
|
||||||
"HMD_PINCH": "HMD + ピンチ",
|
|
||||||
"EYE_PINCH": "つまんで目を合わせる",
|
|
||||||
"EYE_ONLY": "視野のみ",
|
|
||||||
"HMD_ONLY": "HMDのみ",
|
|
||||||
"NONE_INPUT_HELP": "マウスとキーボードをエミュレートしません。\nディスプレイを操作できなくなります。",
|
|
||||||
"UINPUT": "デバイス・エミュレーション",
|
|
||||||
"UINPUT_HELP": "uinput モジュールを使用してデバイスをエミュレートします。\nユーザーが input グループに属している必要があります。\nほとんどのデスクトップ環境で正常に動作することが確認されています。",
|
|
||||||
"WL_VIRTUAL": "Wayland 仮想入力",
|
|
||||||
"WL_VIRTUAL_HELP": "zwlr_virtual_pointer および zwp_virtual_keyboard を使用して、Wayland コンポジタにイベントを送信します。\n一部のデスクトップ環境でのみ、安定して動作します。\nKDE、GNOME、または COSMIC では動作しません。"
|
|
||||||
},
|
},
|
||||||
|
"ASPECT_TITLE": "アスペクト比",
|
||||||
|
"AUTOSTART": "起動時に自動的に実行",
|
||||||
|
"LAUNCH": "起動",
|
||||||
|
"MODE": {
|
||||||
|
"CAGE": "互換モード (Cage)",
|
||||||
|
"NATIVE": "ネイティブモード"
|
||||||
|
},
|
||||||
|
"RES_TITLE": "解像度"
|
||||||
|
},
|
||||||
|
"APP_SETTINGS": {
|
||||||
|
"ALLOW_SLIDING": "掴持中のスティック操作",
|
||||||
|
"ANIMATION_SPEED": "UIアニメーション速度",
|
||||||
"AUTOSTART_APPS": "起動時に実行するアプリ",
|
"AUTOSTART_APPS": "起動時に実行するアプリ",
|
||||||
"HANDSFREE_POINTER": "ハンズフリーモード",
|
"BLOCK_GAME_INPUT": "ゲームへの入力をブロック",
|
||||||
"HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。",
|
"BLOCK_GAME_INPUT_HELP": "オーバーレイにカーソルが合っている間、すべての入力をブロックする",
|
||||||
"UI_GRADIENT_INTENSITY": "UIグラデーションの強さ",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "入力ブロック時にウォッチを無視",
|
||||||
"RESET_PLAYSPACE": "プレイエリアをリセット",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "ウォッチホバー時は入力をブロックしない",
|
||||||
"RESET_PLAYSPACE_HELP": "プレイエリアのオフセットをクリアします。",
|
"BLOCK_POSES_ON_KBD_INTERACTION": "キーボード操作時にポーズ入力をブロック",
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION": "キーボード操作時のポーズをブロック",
|
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "キーボードにカーソルがあり「ゲーム入力をブロック」が有効なとき、ゲームへのポーズ送信を停止する",
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "キーボードがホバーされ、「ゲーム入力をブロック」が有効になっている場合、ゲームがポーズを受信することをブロックします",
|
|
||||||
"LANGUAGE": "言語",
|
|
||||||
"REQUIRES_RESTART": "再起動が必要です",
|
|
||||||
"GRID_OPACITY": "フロアグリッドの不透明度",
|
|
||||||
"GRID_OPACITY_HELP": "スカイボックスが有効なときの床グリッドの不透明度",
|
|
||||||
"BROWSE_ONLINE_CATALOG": "オンラインカタログを閲覧...",
|
|
||||||
"BROWSE_SKYMAPS": "Skymapを閲覧",
|
|
||||||
"COLOR_KEYING": "カラーキーイング",
|
|
||||||
"NO_SKYMAPS_FOUND": "スカイマップが見つかりません",
|
|
||||||
"SELECT_VARIANT": "バリアントを選択",
|
|
||||||
"SHOW_WELCOME_SCREEN": "ウェルカムスクリーンを表示する",
|
|
||||||
"SKYBOX": "スカイボックス",
|
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "このスカイマップは既にダウンロードされています。希望のアクションを選択してください。",
|
|
||||||
"WATCH_VIEW_ANGLE": "Watchの表示角度",
|
|
||||||
"WATCH_VIEW_ANGLE_HELP": "ウォッチのフェードアウト具合を調整する",
|
|
||||||
"BINDINGS": {
|
"BINDINGS": {
|
||||||
"COMP": {
|
"COMP": {
|
||||||
"CLICK": "クリック",
|
"CLICK": "クリック",
|
||||||
"FORCE": "Force",
|
"FORCE": "押し込み強度",
|
||||||
"TOUCH": "タッチ",
|
"TOUCH": "タッチ",
|
||||||
"VALUE": "値",
|
"VALUE": "値",
|
||||||
"PROXIMITY": "近接度",
|
"PROXIMITY": "近接",
|
||||||
"X_AXIS": "X軸",
|
"X_AXIS": "X軸",
|
||||||
"Y_AXIS": "Y軸"
|
"Y_AXIS": "Y軸"
|
||||||
},
|
},
|
||||||
"TYPE": {
|
"TYPE": {
|
||||||
"BUMPER": "バンパー",
|
"BUMPER": "バンパー",
|
||||||
"DPAD_UP": "Dパッド上",
|
"DPAD_UP": "十字キー上",
|
||||||
"DPAD_DOWN": "Dパッド 下",
|
"DPAD_DOWN": "十字キー下",
|
||||||
"DPAD_LEFT": "Dパッド左",
|
"DPAD_LEFT": "十字キー左",
|
||||||
"DPAD_RIGHT": "Dパッド右",
|
"DPAD_RIGHT": "十字キー右",
|
||||||
"JOYSTICK": "ジョイスティック",
|
"JOYSTICK": "ジョイスティック",
|
||||||
"MENU": "メニュー",
|
"MENU": "メニュー",
|
||||||
"SHOULDER": "ショルダー",
|
"SHOULDER": "ショルダーボタン",
|
||||||
"SQUEEZE": "グリップ",
|
"SQUEEZE": "グリップ",
|
||||||
"SYSTEM": "システム",
|
"SYSTEM": "システム",
|
||||||
"THUMBREST": "サムレスト",
|
"THUMBREST": "親指置き場",
|
||||||
"THUMBSTICK": "サムスティック",
|
"THUMBSTICK": "サムスティック",
|
||||||
"TRACKPAD": "トラックパッド",
|
"TRACKPAD": "トラックパッド",
|
||||||
"TRIGGER": "トリガー",
|
"TRIGGER": "トリガー",
|
||||||
"VIEW": "表示"
|
"VIEW": "ビュー"
|
||||||
},
|
},
|
||||||
"CLICK": {
|
"CLICK": {
|
||||||
"ANY": "任意",
|
"ANY": "任意",
|
||||||
"DOUBLE": "ダブルタップ",
|
"DOUBLE": "ダブルタップ",
|
||||||
"TRIPLE": "トリプルタップ",
|
"TRIPLE": "トリプルタップ",
|
||||||
"TYPE": "タップ回数"
|
"TYPE": "タップ数"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"CLICK": "クリック*",
|
"CLICK": "クリック*",
|
||||||
"GRAB": "掴む*",
|
"GRAB": "掴む*",
|
||||||
"ALT_CLICK": "カスタムシェル実行 (configでalt_clickを設定)",
|
"ALT_CLICK": "カスタムシェル実行 (configでalt_clickを設定)",
|
||||||
"SHOW_HIDE": "表示・非表示、再中心化*",
|
"SHOW_HIDE": "表示・非表示・再中心化*",
|
||||||
"TOGGLE_DASHBOARD": "ダッシュボードの切り替え",
|
"TOGGLE_DASHBOARD": "ダッシュボードの切り替え",
|
||||||
"SPACE_DRAG": "Playspaceドラッグ",
|
"SPACE_DRAG": "プレイスペースのドラッグ",
|
||||||
"SPACE_ROTATE": "Playspace 回転",
|
"SPACE_ROTATE": "プレイスペース回転",
|
||||||
"SPACE_RESET": "Playspace リセット",
|
"SPACE_RESET": "プレイスペースのリセット",
|
||||||
"CLICK_MODIFIER_RIGHT": "右クリック修飾キー",
|
"CLICK_MODIFIER_RIGHT": "右クリック修飾キー",
|
||||||
"CLICK_MODIFIER_MIDDLE": "中クリック修飾キー",
|
"CLICK_MODIFIER_MIDDLE": "中クリック修飾キー",
|
||||||
"MOVE_MOUSE": "マウスを移動 (デフォルトでオフの場合)",
|
"MOVE_MOUSE": "マウス移動 (デフォルトでオフ)",
|
||||||
"SCROLL": "スクロール*"
|
"SCROLL": "スクロール*"
|
||||||
},
|
},
|
||||||
"LEFT": "左",
|
"LEFT": "左手",
|
||||||
"RIGHT": "右",
|
"RIGHT": "右",
|
||||||
"COMPONENT": "作動タイプ",
|
"COMPONENT": "入力形式",
|
||||||
"SUBPATH": "アクチュエーション制御",
|
"SUBPATH": "操作ボタン",
|
||||||
"THRESHOLD": "上限値を超えたときに有効化\n下限値を下回ったときに無効化"
|
"THRESHOLD": "上の値を超えると有効\n下の値を下回ると無効"
|
||||||
},
|
},
|
||||||
|
"BROWSE_ONLINE_CATALOG": "オンラインカタログを見る...",
|
||||||
|
"BROWSE_SKYMAPS": "スカイマップを選択",
|
||||||
|
"CAPTURE_METHOD": "画面キャプチャ方式",
|
||||||
|
"CAPTURE_METHOD_HELP": "画面が黒くなったり、表示が乱れたりする場合は\nここを変更して試してください",
|
||||||
|
"COLOR_KEYING": "カラーキー",
|
||||||
|
"COLOR_PALETTE": "カラーパレット",
|
||||||
|
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択。\nカスタムパレットの作成方法はウェブサイトを確認!",
|
||||||
|
"COLOR_PALETTES": "カラーパレット",
|
||||||
|
"COLOR_PALETTE_CURRENT": "現在適用中のテーマ",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "カスタムテーマを追加!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Webマニュアルを開く",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用。",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS": "PipeWireトークンを消去",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "次回起動時に画面選択を促す",
|
||||||
|
"CLEAR_SAVED_STATE": "保存済み状態をリセット",
|
||||||
|
"CLEAR_SAVED_STATE_HELP": "セットとオーバーレイの位置をリセット",
|
||||||
|
"CLICK_FREEZE_TIME_MS": "クリック固定時間 (ms)",
|
||||||
|
"CLICK_FREEZE_TIME_MS_HELP": "ダブルクリックの精度を向上させます",
|
||||||
|
"CLOCK_12H": "12時間表記",
|
||||||
|
"CONTROLS": "操作設定",
|
||||||
|
"DELETE_ALL_CONFIGS": "設定をリセット",
|
||||||
|
"DELETE_ALL_CONFIGS_HELP": "conf.d内のすべての設定ファイルを削除する",
|
||||||
|
"DOUBLE_CURSOR_FIX": "カーソル二重表示の修正",
|
||||||
|
"DOUBLE_CURSOR_FIX_HELP": "カーソルが2つ表示される場合に有効にする",
|
||||||
|
"DEFAULT_OVERLAY_SCALE": "デフォルトのオーバーレイサイズ",
|
||||||
|
"DEFAULT_OVERLAY_SCALE_HELP": "新しいオーバーレイをこの倍率で表示する。",
|
||||||
|
"DEFAULT_CURVATURE": "デフォルトのオーバーレイ曲率",
|
||||||
|
"DEFAULT_OPACITY": "デフォルトのオーバーレイ不透明度",
|
||||||
|
"DEFAULT_POSITIONING": "オーバーレイのデフォルト配置",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "新規オーバーレイにのみ適用",
|
||||||
"ENABLED": "有効",
|
"ENABLED": "有効",
|
||||||
"INPUT_EMULATION_METHOD": "入力エミュレーション方法",
|
"FEATURES": "機能",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "マウスやキーボードの入力が\n認識されない場合は、ここを変更してみてください。",
|
"FOCUS_FOLLOWS_MOUSE_MODE": "トリガー接触でマウス移動",
|
||||||
"INPUT_PROFILES": "入力バインドの変更",
|
"HANDSFREE_POINTER": "ハンズフリーモード",
|
||||||
"INPUT_PROFILES_HELP": "OpenXRコントローラーの入力バインディング",
|
"HANDSFREE_POINTER_HELP": "コントローラーがない時に使用する入力方式。\n左手のピンチで掴み、右手のピンチでクリック。",
|
||||||
"NOT_SUPPORTED": "未対応",
|
"HANDSFREE_ALT_TAB": "アプリ切替の方向",
|
||||||
"ENABLE_WATCH": "Watchを有効にする",
|
"HANDSFREE_ALT_TAB_HELP": "Super+Xを押しながら目的のウィンドウに向け、離すとフォーカスが切り替わる。",
|
||||||
"SPACE_DRAG": "Space drag",
|
"HIDE_GRAB_HELP": "掴み方のヒントを隠す",
|
||||||
"SPACE_GRAVITY_DAMPING": "減衰",
|
"HIDE_USERNAME": "ユーザー名を隠す",
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "動きを減速させるための人工的な抵抗です。0.1 - 強い抵抗、1.0 - 抵抗なし",
|
"INPUT_EMULATION_METHOD": "入力エミュレーション方式",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH": "スリングの強さ",
|
"INPUT_EMULATION_METHOD_HELP": "マウスやキーボードの入力が\n反応しない場合はここを変更してください。",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Space-drag 後の重力による打ち出し強度の倍率です。\n0.0 - 全く動きません、2.0 - 強度が2倍になります",
|
"INPUT_CAPTURE_METHOD": "入力キャプチャ方式",
|
||||||
"SPACE_GRAVITY_GRAVITY": "重力",
|
"INPUT_CAPTURE_METHOD_HELP": "WayVR内で物理周辺機器を使用可能にする。\n Super+Z: WayVRと実デスクトップの間で入力を切り替え\n Super+X: WayVRアプリ間を切り替え",
|
||||||
"SPACE_GRAVITY_GRAVITY_HELP": "下向きの力の強さ。0.0 - 重力なし",
|
"INPUT_PROFILES": "入力バインドを変更",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION": "地面の摩擦",
|
"INPUT_PROFILES_HELP": "OpenXRコントローラー入力バインド",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "地面に触れている際に、移動を遅らせる摩擦の強さです。\n0.0 - 摩擦なし(氷の上のような状態)、1.0 - 粗い表面",
|
"INVERT_SCROLL_DIRECTION_X": "水平スクロール方向を反転",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "床の高さ",
|
"INVERT_SCROLL_DIRECTION_Y": "垂直スクロール方向を反転",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "床のY座標です。この高さに達すると重力が停止します。",
|
"KEYBOARD_MIDDLE_CLICK": "キーボード中クリック",
|
||||||
"SAVE": "保存",
|
"KEYBOARD_MIDDLE_CLICK_HELP": "紫色のレーザーで\n入力する際の修飾キー",
|
||||||
"CANCEL": "キャンセル",
|
"KEYBOARD_SOUND_ENABLED": "キーボード入力音",
|
||||||
"WHISPER": {
|
"LANGUAGE": "言語",
|
||||||
"NEED_TO_DOWNLOAD_MODEL": "選択されたモデルをダウンロードする必要があります。\n今すぐダウンロードしますか?",
|
"LEFT_HANDED_MOUSE": "左利きマウス",
|
||||||
"REMOVE_UNUSED_MODELS": "文字起こし機能をオフにします。\n空き容量を増やすために、ダウンロード済みのモデルファイルを削除しますか?"
|
"LEFT_HANDED_MOUSE_HELP": "マウスボタンを入れ替えて使用する場合にチェック",
|
||||||
|
"LONG_PRESS_DURATION": "長押し時間",
|
||||||
|
"LOOK_AND_FEEL": "外観と操作感",
|
||||||
|
"MISC": "その他",
|
||||||
|
"NOTIFICATIONS_ENABLED": "通知を有効にする",
|
||||||
|
"NOTIFICATIONS_SOUND_ENABLED": "通知音",
|
||||||
|
"NOT_SUPPORTED": "非対応",
|
||||||
|
"NO_SKYMAPS_FOUND": "スカイマップが見つかりません",
|
||||||
|
"OPAQUE_BACKGROUND": "不透明な背景",
|
||||||
|
"OPTION": {
|
||||||
|
"ANCHORED_HELP": "センターマーカーと共に移動。推奨。",
|
||||||
|
"FLOATING_HELP": "独立して移動し、中心位置を再設定する。\n紛失しやすいため、あまり推奨されない。",
|
||||||
|
"STATIC_HELP": "ワールド基準で固定される。",
|
||||||
|
"AUTO": "自動",
|
||||||
|
"AUTO_HELP": "対応していればScreenCopy GPUを、\nそうでなければPipeWire GPUを使用。",
|
||||||
|
"EYE_ONLY": "視線レーザー",
|
||||||
|
"EYE_PINCH": "視線 + ピンチ",
|
||||||
|
"HMD_ONLY": "HMDレーザー",
|
||||||
|
"HMD_PINCH": "HMD + ピンチ",
|
||||||
|
"NONE": "なし",
|
||||||
|
"NONE_INPUT_HELP": "マウスとキーボードをエミュレートしない。\n画面とのインタラクトができなくなる。",
|
||||||
|
"NONE_INPUT_CAPTURE_HELP": "マウスとキーボードをキャプチャしない。\nWayVR内で起動したアプリで物理マウスや\nキーボードが使用できなくなる。",
|
||||||
|
"PIPEWIRE_HELP": "高速なGPUキャプチャ。\nデスクトップの標準的な方式。",
|
||||||
|
"PW_FALLBACK_HELP": "CPU負荷が高い低速な方式。\nPipeWire GPUが動作しない場合に試行すること",
|
||||||
|
"SCREENCOPY_GPU_HELP": "高速で、画面共有のポップアップが表示されない。\n対応:Hyprland, Niri, River, Sway",
|
||||||
|
"SCREENCOPY_HELP": "低速だが、画面共有のポップアップが出ない。\n対応: Hyprland, Niri, River, Sway",
|
||||||
|
"UINPUT": "デバイスエミュレーション",
|
||||||
|
"UINPUT_HELP": "uinputモジュールを使用してデバイスをエミュレートします。\nほとんどのデスクトップ環境で良好に動作します。",
|
||||||
|
"EVDEV_HELP": "入力デバイスを排他的に使用する。\nユーザーが input グループに属している必要がある。",
|
||||||
|
"WL_VIRTUAL": "Wayland仮想入力",
|
||||||
|
"WL_VIRTUAL_HELP": "zwlr_virtual_pointer と zwp_virtual_keyboard を使用して\nWayland コンポジターにイベントを送信する。\nデスクトップ環境によって安定性が異なり、\nKDE、GNOME、COSMIC では動作しない。"
|
||||||
},
|
},
|
||||||
"WHISPER_MODEL": "文字起こしモデル",
|
"POINTER_ACCELERATION": "マウス加速",
|
||||||
"WHISPER_MODEL_HELP": "使用するWhisperモデル。\nモデルが大きいほど精度は向上しますが、\nVRAMの消費量が増加します。"
|
"POINTER_ACCELERATION_HELP": "オン: 適応型マウス加速\nオフ: 等速",
|
||||||
|
"POINTER_LERP_FACTOR": "ポインタの平滑化",
|
||||||
|
"POINTER_SPEED": "マウス速度",
|
||||||
|
"REQUIRES_RESTART": "要再起動",
|
||||||
|
"RESET_PLAYSPACE": "プレイスペースをリセット",
|
||||||
|
"RESET_PLAYSPACE_HELP": "プレイスペースのオフセットをリセットする。",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "プレイスペースの中心を保存",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "現在のプレイスペースを、プレイスペースリセットのバインディングに使用する。",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "プレイスペースの中心をリセット",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "設定済みのプレイスペースの中心点をリセットする。",
|
||||||
|
"RESTART_SOFTWARE": "ソフトウェアを再起動",
|
||||||
|
"RESTART_SOFTWARE_HELP": "再起動が必要な設定を適用する",
|
||||||
|
"ROUND_MULTIPLIER": "UIの角の丸み",
|
||||||
|
"SCREEN_RENDER_DOWN": "低解像度で画面をレンダリング",
|
||||||
|
"SCREEN_RENDER_DOWN_HELP": "高解像度ディスプレイでのジャギーを軽減する",
|
||||||
|
"SCROLL_SPEED": "スクロール速度",
|
||||||
|
"SELECT_VARIANT": "バリアントを選択",
|
||||||
|
"SNAP_ANGLE_DEG": "ウィンドウのピッチ・ロール吸着角",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "掴んでいるウィンドウが、ピッチ軸とロール軸でこの角度にスナップします。",
|
||||||
|
"ENABLE_WATCH": "ウォッチを有効にする",
|
||||||
|
"SETS_ON_WATCH": "ウォッチにセットを表示",
|
||||||
|
"SHOW_WELCOME_SCREEN": "ウェルカムスクリーンを表示",
|
||||||
|
"SKYBOX": "スカイマップ",
|
||||||
|
"SKYMAP_ALREADY_DOWNLOADED": "このスカイマップはすでにダウンロード済みです。操作を選択してください。",
|
||||||
|
"SPACE_DRAG": "プレイスペース",
|
||||||
|
"SPACE_DRAG_MULTIPLIER": "プレイスペース移動倍率",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "プレイスペース移動時にオーバーレイをその場に残す",
|
||||||
|
"SPACE_DRAG_UNLOCKED": "全軸でスペースドラッグを許可",
|
||||||
|
"SPACE_GRAVITY_DAMPING": "減衰",
|
||||||
|
"SPACE_GRAVITY_DAMPING_HELP": "動きを緩やかにする擬似的な抵抗。0.1:抵抗大、1.0:抵抗なし",
|
||||||
|
"SPACE_GRAVITY_FLING_STRENGTH": "弾き飛ばし強度",
|
||||||
|
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "スペースドラッグ後の重力投射の強度倍率。\n0.0:動きなし、2.0:強度2倍",
|
||||||
|
"SPACE_GRAVITY_GRAVITY": "重力",
|
||||||
|
"SPACE_GRAVITY_GRAVITY_HELP": "下向きの力の強さ。0.0は無重力",
|
||||||
|
"SPACE_GRAVITY_GROUND_FRICTION": "接地摩擦",
|
||||||
|
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "接地時の摩擦量。\n0.0 - 摩擦なし(氷の上のように)、1.0 - 粗い表面",
|
||||||
|
"SPACE_GRAVITY_FLOOR_HEIGHT": "床の高さ",
|
||||||
|
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "床のY軸位置。この高さに達すると重力による落下が止まる。",
|
||||||
|
"SPACE_ROTATE_UNLOCKED": "全軸でのプレイスペース回転を許可",
|
||||||
|
"TROUBLESHOOTING": "トラブルシューティング",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UIグラデーションの強度",
|
||||||
|
"UPRIGHT_SCREEN_FIX": "画面直立補正",
|
||||||
|
"UPRIGHT_SCREEN_FIX_HELP": "一部のデスクトップで画面の向きを垂直に固定する",
|
||||||
|
"USE_PASSTHROUGH": "パススルーを有効にする",
|
||||||
|
"USE_PASSTHROUGH_HELP": "XRランタイムが対応している場合、パススルーを有効にする",
|
||||||
|
"USE_SKYBOX": "スカイマップを表示",
|
||||||
|
"USE_SKYBOX_HELP": "シーンアプリやパススルーがない場合にスカイマップを表示する",
|
||||||
|
"WATCH_VIEW_ANGLE": "ウォッチの表示角度",
|
||||||
|
"WATCH_VIEW_ANGLE_HELP": "ウォッチが消えていくタイミングを調整",
|
||||||
|
"WHISPER": {
|
||||||
|
"NEED_TO_DOWNLOAD_MODEL": "選択したモデルをダウンロードする必要があります。\n今すぐダウンロードしますか?",
|
||||||
|
"REMOVE_UNUSED_MODELS": "音声入力機能をオフにします。\n空き容量を増やすため、ダウンロード済みのWhisperモデルを削除しますか?"
|
||||||
|
},
|
||||||
|
"WHISPER_MODEL": "音声認識モデル",
|
||||||
|
"WHISPER_MODEL_HELP": "使用するWhisperモデルを選択。\nモデルが大きいほど精度は向上するが、\nVRAMの消費量が増える。",
|
||||||
|
"GRID_OPACITY": "フロアグリッドの不透明度",
|
||||||
|
"GRID_OPACITY_HELP": "スカイマップ有効時のフロアグリッドの不透明度",
|
||||||
|
"XWAYLAND_BY_DEFAULT": "デフォルトで互換モードでアプリを起動",
|
||||||
|
"SAVE": "保存",
|
||||||
|
"CANCEL": "キャンセル"
|
||||||
},
|
},
|
||||||
"HELLO": "こんにちは!",
|
"APPLICATION_LAUNCHER": "アプリランチャー",
|
||||||
|
"APPLICATION_STARTED": "アプリが起動しました",
|
||||||
|
"APPLICATIONS": "アプリ",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
"VOLUME": "音量",
|
"AUTO_SWITCH_TO_VR_AUDIO": "VRオーディオへ自動切り替え",
|
||||||
"SETTINGS": "オーディオ設定",
|
"CARDS": "サウンドカード",
|
||||||
"AUTO_SWITCH_TO_VR_AUDIO": "VRオーディオに自動切り替え",
|
|
||||||
"SPEAKERS": "スピーカー",
|
|
||||||
"MICROPHONES": "マイク",
|
|
||||||
"CARDS": "カード",
|
|
||||||
"SELECT_AUDIO_CARD_PROFILE": "オーディオカードプロファイルを選択",
|
|
||||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "VRスピーカーが見つかりませんでした。手動で切り替えてください。",
|
|
||||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "VRマイクが見つかりませんでした。手動で切り替えてください。",
|
|
||||||
"FAILED_TO_SWITCH_MICROPHONE": "マイクの切り替えに失敗しました",
|
"FAILED_TO_SWITCH_MICROPHONE": "マイクの切り替えに失敗しました",
|
||||||
"MICROPHONE_SET_SUCCESSFULLY": "マイクの設定が完了しました",
|
"MICROPHONE_SET_SUCCESSFULLY": "マイクを設定しました",
|
||||||
"SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定しました"
|
"MICROPHONES": "マイク",
|
||||||
|
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "VRマイクが見つかりません。手動で切り替えてください。",
|
||||||
|
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "VRスピーカーが見つかりませんでした。手動で切り替えてください。",
|
||||||
|
"SELECT_AUDIO_CARD_PROFILE": "オーディオカードプロファイルを選択",
|
||||||
|
"SETTINGS": "オーディオ設定",
|
||||||
|
"SPEAKERS": "スピーカー",
|
||||||
|
"SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定完了",
|
||||||
|
"VOLUME": "音量"
|
||||||
},
|
},
|
||||||
"ACTIONS": {
|
"CLOSE_WINDOW": "ウィンドウを閉じる",
|
||||||
"RECENTER_PLAYSPACE": "プレイスペースを再中央"
|
"CREATION_DATE": "作成日",
|
||||||
|
"DEBUG_INFO": "デバッグ情報",
|
||||||
|
"DISPLAY_BRIGHTNESS": "ディスプレイの明るさ",
|
||||||
|
"DONATE": {
|
||||||
|
"SUPPORT_US": "支援する",
|
||||||
|
"DESCRIPTION": "WayVRは、2人の開発者が空き時間を利用して作っている小規模なプロジェクトです。もしこのソフトを気に入っていただけたら、ぜひサポートをお願いします。皆様の寄付が開発の大きな励みになります。",
|
||||||
|
"THANK_YOU_WAYVR": "WayVRチームより、感謝を込めて!",
|
||||||
|
"BUTTON_TOOLTIP": "Open Collectiveで寄付する",
|
||||||
|
"CURRENT_SUPPORTERS": "現在のサポーター",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "{USER}さんにサポートされています|{USER}さんに感謝!|{USER}さんのご支援で成り立っています|{USER}さんが支えてくれています|{USER}さんの後押しのおかげです|{USER}さんが後援しています|{USER}さんのご協力に感謝|{USER}さんが応援してくれています|本日のサポーターは{USER}さんです",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "{USER}さんの優しさに感謝|{USER}さんが背中を押してくれました|{USER}さんの心強いサポート|{USER}さんが彩りを添えてくれました|{USER}さんのおかげで前進しています|{USER}さんの温かいご支援|{USER}さんが笑顔を届けてくれました|{USER}さんが道を照らしてくれました|{USER}さんに心から感謝して",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "今日のMVPは{USER}さん!|{USER}さんが神降臨!|{USER}さんが限界突破させてくれた!|{USER}さんのパワーで爆走中!|救世主、現る:{USER}さん!|{USER}さんが文明を支えています|{USER}さんの情熱が燃料です!|本日のスーパーヒーロー:{USER}さん!|{USER}さんがバグをなぎ倒してくれた!|{USER}さんの応援でテンションMAX!|全宇宙から{USER}さんに拍手を!"
|
||||||
},
|
},
|
||||||
|
"DOWNLOAD": "ダウンロード",
|
||||||
|
"DOWNLOADER": "ダウンローダー",
|
||||||
|
"WELCOME": {
|
||||||
|
"ALL_SET": "準備完了!",
|
||||||
|
"BASICS": "これらの基本を抑えれば、簡単にWayVRを使い始めることができる。",
|
||||||
|
"CENTER_MARKER": "センターマーカーはリセンタリング時に目の前に現れる印だ。この周りにオーバーレイを配置しよう!",
|
||||||
|
"DOUBLE_PRESS_TO_TOGGLE": "セットの表示、再中心化、または非表示にするには、Bボタン(Index)またはYボタン(Meta)をダブルプレスして下さい。今すぐ試してみよう。",
|
||||||
|
"FEATURES_DOCUMENTATION": "他にもカスタマイズ次第で多くの機能が活用できます。詳細はドキュメントを確認してください:",
|
||||||
|
"FINISH_TUTORIAL": "チュートリアルを終了",
|
||||||
|
"GRAB_BOTH_HANDS": "セット内の特定のオーバーレイを移動させるには、両手で掴んでください。",
|
||||||
|
"GRAB_ONE_HAND": "片手で掴んでセットを移動させよう。",
|
||||||
|
"GREETING": "ようこそ!",
|
||||||
|
"GUIDE_INTRO": "まずは基本操作から案内する。",
|
||||||
|
"LASER_COLORS": "レーザーの色",
|
||||||
|
"LASER_FUNCTIONALITY": "WayVRの機能の多くは、UI要素を操作するレーザーの色によって決まります。ボタンを押し込む必要はなく、軽く触れるだけで操作可能です!",
|
||||||
|
"LAST_PAGE_INFO": "最終ページに到達すると、このチュートリアルは表示されなくなります。",
|
||||||
|
"LOOK_AT_LEFT_WRIST": "左手首を見てください。それがあなたのウォッチです。",
|
||||||
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "中クリックモード:紫色のレーザー",
|
||||||
|
"MOVING_YOUR_SET": "セットの移動",
|
||||||
|
"NEXT_BUTTON": "下の「次へ」ボタンを押して開始してください。",
|
||||||
|
"REGULAR_MODE_BLUE_LASER": "通常モード:青色レーザー",
|
||||||
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "コントローラーのグリップボタンでこのウィンドウを移動させる。",
|
||||||
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "右クリックモード:オレンジ色のレーザー",
|
||||||
|
"THANKS_FOR_INSTALLING": "WayVRをインストールしてくれてありがとう!",
|
||||||
|
"WATCH": "ウォッチ",
|
||||||
|
"WORKING_SET": "使用中のセット"
|
||||||
|
},
|
||||||
|
"DOWNLOAD_AGAIN": "再ダウンロード",
|
||||||
|
"DOWNLOADING_FILE": "ファイルをダウンロード中...",
|
||||||
|
"FAILED_TO_LAUNCH_APPLICATION": "アプリケーションの起動に失敗しました:",
|
||||||
|
"GAME_LAUNCHED": "ゲームを起動しました",
|
||||||
|
"GAME_LIST": {
|
||||||
|
"NO_GAMES_FOUND": "ゲームが見つかりません",
|
||||||
|
"RUNNING_GAMES_LIST": "実行中のゲーム一覧"
|
||||||
|
},
|
||||||
|
"GAMES": "ゲーム",
|
||||||
|
"GENERAL_SETTINGS": "一般設定",
|
||||||
|
"GETTING_STARTED": "はじめに",
|
||||||
|
"HEIGHT": "高さ",
|
||||||
|
"HELLO": "こんにちは!",
|
||||||
|
"HELLO_USER": "こんにちは、{USER}!",
|
||||||
|
"HIDE": "非表示",
|
||||||
|
"HOME_SCREEN": "ホーム",
|
||||||
|
"MODIFICATION_DATE": "更新日",
|
||||||
|
"MONADO_RUNTIME": "Monado ランタイム",
|
||||||
|
"LOADING": "読み込み中...",
|
||||||
"POPUP_ADD_DISPLAY": {
|
"POPUP_ADD_DISPLAY": {
|
||||||
"RESOLUTION": "解像度"
|
"RESOLUTION": "解像度"
|
||||||
},
|
},
|
||||||
"WIDTH": "幅",
|
"PROCESS": {
|
||||||
"HEIGHT": "高さ",
|
"FORCE_KILL": "強制終了",
|
||||||
"HIDE": "隠す",
|
"STOP": "停止"
|
||||||
"REMOVE": "削除",
|
|
||||||
"SHOW": "表示",
|
|
||||||
"FAILED_TO_LAUNCH_APPLICATION": "アプリケーションの起動に失敗しました:",
|
|
||||||
"APPLICATION_STARTED": "アプリケーションが起動しました",
|
|
||||||
"CLOSE_WINDOW": "ウィンドウを閉じる",
|
|
||||||
"GAME_LIST": {
|
|
||||||
"NO_GAMES_FOUND": "ゲームが見つかりませんでした",
|
|
||||||
"RUNNING_GAMES_LIST": "実行中のゲーム一覧"
|
|
||||||
},
|
},
|
||||||
"TERMINATE_PROCESS": "プロセスを終了する",
|
|
||||||
"GAME_LAUNCHED": "ゲームが起動しました",
|
|
||||||
"APP_LAUNCHER": {
|
|
||||||
"MODE": {
|
|
||||||
"NATIVE": "ネイティブモード",
|
|
||||||
"CAGE": "互換モード(Cage)"
|
|
||||||
},
|
|
||||||
"RES_TITLE": "解像度",
|
|
||||||
"ASPECT_TITLE": "アスペクト",
|
|
||||||
"ASPECT": {
|
|
||||||
"WIDE": "ワイド",
|
|
||||||
"SEMI_WIDE": "半広角",
|
|
||||||
"SQUARE": "正方形",
|
|
||||||
"SEMI_TALL": "半縦長",
|
|
||||||
"TALL": "縦長"
|
|
||||||
},
|
|
||||||
"POS_TITLE": "配置",
|
|
||||||
"POS": {
|
|
||||||
"FLOATING": "フローティング",
|
|
||||||
"ANCHORED": "固定",
|
|
||||||
"STATIC": "固定",
|
|
||||||
"FLOATING_HELP": "独立して移動し、表示時に中央に再配置されます。",
|
|
||||||
"ANCHORED_HELP": "中央マーカーに対して固定された位置に留まります。",
|
|
||||||
"STATIC_HELP": "どのセットにも属していません。リセンターされません。"
|
|
||||||
},
|
|
||||||
"AUTOSTART": "起動時に自動実行",
|
|
||||||
"LAUNCH": "起動"
|
|
||||||
},
|
|
||||||
"DISPLAY_BRIGHTNESS": "ディスプレイの明るさ",
|
|
||||||
"PROCESS_LIST": "プロセスリスト",
|
"PROCESS_LIST": "プロセスリスト",
|
||||||
"REFRESH": "更新",
|
"REFRESH": "更新",
|
||||||
"PROCESS": {
|
"REMOVE": "削除",
|
||||||
"STOP": "停止",
|
|
||||||
"FORCE_KILL": "強制終了"
|
|
||||||
},
|
|
||||||
"DEBUG_INFO": "デバッグ情報",
|
|
||||||
"CREATION_DATE": "作成日",
|
|
||||||
"DOWNLOADER": "ダウンローダー",
|
|
||||||
"DOWNLOAD_AGAIN": "再ダウンロード",
|
|
||||||
"DOWNLOADING_FILE": "ファイルをダウンロード中...",
|
|
||||||
"GETTING_STARTED": "はじめに",
|
|
||||||
"MODIFICATION_DATE": "更新日",
|
|
||||||
"LOADING": "読み込み中...",
|
|
||||||
"APPLY": "適用",
|
"APPLY": "適用",
|
||||||
"RELOAD_FROM_DISK": "ディスクからリロード",
|
"RELOAD_FROM_DISK": "ディスクから再読み込み",
|
||||||
"TARGET_PATH": "ターゲットパス",
|
"SETTINGS": "設定",
|
||||||
|
"SHOW": "表示",
|
||||||
|
"TARGET_PATH": "保存先パス",
|
||||||
|
"TERMINATE_PROCESS": "プロセスを終了",
|
||||||
"VERSION": "バージョン",
|
"VERSION": "バージョン",
|
||||||
"DONATE": {
|
"WIDTH": "幅",
|
||||||
"SUPPORT_US": "私たちを支援する",
|
"PINNED_APPS": "固定済みアプリ",
|
||||||
"DESCRIPTION": "私たちは、空き時間にWayVRを開発している2人の開発者からなる小さなチームです。もしこのソフトウェアを気に入っていただけたなら、ぜひ支援をご検討ください。皆様からの寄付は、開発を継続していくための大きな助けとなります。",
|
"SAVED_TO_FAVOURITES": "固定済みアプリに保存した",
|
||||||
"BUTTON_TOOLTIP": "Open Collectiveで寄付する",
|
"ADD_TO_FAVOURITES": "固定済みアプリに追加",
|
||||||
"CURRENT_SUPPORTERS": "現在のサポーター",
|
"ADD_TO_FAVOURITES_HINT": "プリセットを保存し、アプリドロワーに固定する",
|
||||||
"THANK_YOU_WAYVR": "WayVRチーム一同より、感謝を込めて!"
|
"REMOVE_FROM_FAVOURITES": "固定済みアプリから外す",
|
||||||
},
|
"EMPTY": "なし"
|
||||||
"WELCOME": {
|
|
||||||
"ALL_SET": "準備完了です!",
|
|
||||||
"BASICS": "これらの基本操作を学ぶことで、WayVRを簡単に使い始めることができます。",
|
|
||||||
"CENTER_MARKER": "センターマーカーは、セットの中心を決定します。",
|
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "Bボタン (Index) または Yボタン (Meta) をダブルプレスして、ワークスペースの表示/非表示を切り替えます。今すぐ試してみてください。",
|
|
||||||
"FEATURES_DOCUMENTATION": "他にもカスタマイズする価値のある機能がたくさんあります。詳細については、以下のドキュメントを確認してください。",
|
|
||||||
"FINISH_TUTORIAL": "チュートリアルを終了する",
|
|
||||||
"GRAB_BOTH_HANDS": "セット内の特定のオーバーレイを移動させたい場合は、両手で掴んでください。",
|
|
||||||
"GRAB_ONE_HAND": "片手で掴んでセットを移動させます。",
|
|
||||||
"GREETING": "こんにちは!",
|
|
||||||
"GUIDE_INTRO": "最初の手順をご案内します。",
|
|
||||||
"LASER_COLORS": "レーザーの色",
|
|
||||||
"LASER_FUNCTIONALITY": "WayVRの機能の多くは、UI要素を操作する際に使用されるレーザーの色に依存しています。これらのボタンは押す必要はなく、ただ触れるだけで操作できます!",
|
|
||||||
"LAST_PAGE_INFO": "最後のページに到達すると、このチュートリアルは表示されなくなります。",
|
|
||||||
"LOOK_AT_LEFT_WRIST": "左手首を見てください。それがあなたのWatchです。",
|
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— ミドルクリックモード:紫色のレーザー",
|
|
||||||
"MOVING_YOUR_SET": "セットを移動中",
|
|
||||||
"NEXT_BUTTON": "「次へ」ボタンを押して開始してください。",
|
|
||||||
"REGULAR_MODE_BLUE_LASER": "— 通常モード: ブルーレーザー",
|
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "コントローラーのグリップアクションを使用して、このウィンドウの位置を再設定します。",
|
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— 右クリックモード:オレンジ色のレーザー",
|
|
||||||
"THANKS_FOR_INSTALLING": "WayVRをインストールしていただきありがとうございます!",
|
|
||||||
"WATCH": "Watch",
|
|
||||||
"WORKING_SET": "ワーキングセット"
|
|
||||||
},
|
|
||||||
"DOWNLOAD": "ダウンロード"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,110 +1,56 @@
|
||||||
{
|
{
|
||||||
|
"DEFINITIONS": {
|
||||||
|
"ANCHORED": "Przytwierdzone",
|
||||||
|
"FLOATING": "Pływający",
|
||||||
|
"STATIC": "Stacjonarny",
|
||||||
|
"SET": "Zestaw",
|
||||||
|
"WATCH": "Zegarek",
|
||||||
|
"DASHBOARD": "Panel sterowania",
|
||||||
|
"EDIT_MODE": "Tryb edycji",
|
||||||
|
"SETTINGS": "Ustawienia",
|
||||||
|
"KEYBOARD": "Klawiatura",
|
||||||
|
"TASKBAR": "Pasek zadań",
|
||||||
|
"FEATURES": "Funkcje",
|
||||||
|
"OVERLAY": "Nakładka",
|
||||||
|
"SKYMAP": "Skymap",
|
||||||
|
"PLAYSPACE": "Przestrzeń gry",
|
||||||
|
"D_PAD": "D-pad"
|
||||||
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"RECENTER_PLAYSPACE": "Wycentruj przestrzeń"
|
"RECENTER_PLAYSPACE": "Resetuj centrum przestrzeni gry"
|
||||||
|
},
|
||||||
|
"APP_LAUNCHER": {
|
||||||
|
"ASPECT": {
|
||||||
|
"SEMI_TALL": "Półwysoki",
|
||||||
|
"SEMI_WIDE": "Półszeroki",
|
||||||
|
"SQUARE": "Kwadratowy",
|
||||||
|
"TALL": "W pionie",
|
||||||
|
"WIDE": "Szeroki"
|
||||||
|
},
|
||||||
|
"ASPECT_TITLE": "Proporcje",
|
||||||
|
"AUTOSTART": "Uruchamiaj automatycznie przy starcie",
|
||||||
|
"LAUNCH": "Uruchom",
|
||||||
|
"MODE": {
|
||||||
|
"CAGE": "Tryb kompatybilności (Cage)",
|
||||||
|
"NATIVE": "Tryb natywny"
|
||||||
|
},
|
||||||
|
"RES_TITLE": "Rozdzielczość"
|
||||||
},
|
},
|
||||||
"APP_SETTINGS": {
|
"APP_SETTINGS": {
|
||||||
"HIDE_USERNAME": "Ukryj nazwę użytkownika",
|
"ALLOW_SLIDING": "Interakcja drążkiem podczas przesuwania",
|
||||||
"OPAQUE_BACKGROUND": "Nieprzezroczyste tło",
|
|
||||||
"LOOK_AND_FEEL": "Wygląd i działanie",
|
|
||||||
"HIDE_GRAB_HELP": "Ukryj pomoc dotyczącą chwytania",
|
|
||||||
"ANIMATION_SPEED": "Prędkość animacji UI",
|
"ANIMATION_SPEED": "Prędkość animacji UI",
|
||||||
"ROUND_MULTIPLIER": "Zaokrąglenie krawędzi UI",
|
"AUTOSTART_APPS": "Aplikacje uruchamiane przy starcie",
|
||||||
"USE_SKYBOX": "Włącz niebo",
|
"BLOCK_GAME_INPUT": "Blokuj wejście do gry",
|
||||||
"USE_PASSTHROUGH": "Włącz passthrough",
|
"BLOCK_GAME_INPUT_HELP": "Blokuje wszystkie wejścia, gdy kursor znajduje się nad nakładką",
|
||||||
"CLOCK_12H": "Zegar 12-godzinny",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignoruj zegarek przy blokowaniu wejścia",
|
||||||
"FEATURES": "Funkcje",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Nie blokuj wejścia podczas najechania na zegarek",
|
||||||
"NOTIFICATIONS_ENABLED": "Włącz powiadomienia",
|
"BLOCK_POSES_ON_KBD_INTERACTION": "Blokuj pozę podczas interakcji z klawiaturą",
|
||||||
"NOTIFICATIONS_SOUND_ENABLED": "Dźwięki powiadomień",
|
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blokuje przesyłanie pozycji do gry, gdy kursor znajduje się nad klawiaturą, a opcja „Blokuj wejście do gry” jest włączona",
|
||||||
"KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury",
|
|
||||||
"SPACE_DRAG_MULTIPLIER": "Mnożnik przesuwania przestrzeni",
|
|
||||||
"SPACE_DRAG_UNLOCKED": "Pozwól na przesuwanie przestrzeni na wszystkich osiach",
|
|
||||||
"SPACE_ROTATE_UNLOCKED": "Pozwól na rotację przestrzeni na wszystkich osiach",
|
|
||||||
"BLOCK_GAME_INPUT": "Blokuj input z gry",
|
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Nie blokuj inputu gry, gdy zegarek jest używany",
|
|
||||||
"CONTROLS": "Sterowanie",
|
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "Ruch myszą po dotknięciu spustu",
|
|
||||||
"LEFT_HANDED_MOUSE": "Myszka dla leworęcznych",
|
|
||||||
"ALLOW_SLIDING": "Interakcja z drążkami podczas chwytania",
|
|
||||||
"INVERT_SCROLL_DIRECTION_X": "Odwróć kierunek przewijania w poziomie",
|
|
||||||
"INVERT_SCROLL_DIRECTION_Y": "Odwróć kierunek przewijania w pionie",
|
|
||||||
"SCROLL_SPEED": "Prędkość przewijania",
|
|
||||||
"LONG_PRESS_DURATION": "Czas długiego przytrzymania",
|
|
||||||
"POINTER_LERP_FACTOR": "Wygładzanie wskaźnika",
|
|
||||||
"CLICK_FREEZE_TIME_MS": "Czas zamrożenia po kliknięciu (ms)",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "Uruchamiaj aplikacje domyślnie w trybie kompatybilności",
|
|
||||||
"UPRIGHT_SCREEN_FIX": "Naprawa pozycji ekranu",
|
|
||||||
"DOUBLE_CURSOR_FIX": "Naprawa podwójnego kursora",
|
|
||||||
"SCREEN_RENDER_DOWN": "Renderuj ekran w niższej rozdzielczości",
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Naprawia pionowe ekrany na niektórych komputerach",
|
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Włącz to, jeśli widzisz 2 kursory",
|
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Pomaga w precyzji podwójnego kliknięcia",
|
|
||||||
"LEFT_HANDED_MOUSE_HELP": "Użyj tego, jeśli przyciski myszy są zamienione",
|
|
||||||
"BLOCK_GAME_INPUT_HELP": "Blokuje wszystkie dane wejściowe, gdy kursor najedzie na nakładkę",
|
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Nie blokuj inputu, gdy wskaźnik jest najedzony",
|
|
||||||
"USE_SKYBOX_HELP": "Wyświetlaj niebo, jeśli nie ma aplikacji sceny lub passthrough",
|
|
||||||
"USE_PASSTHROUGH_HELP": "Pozwól na passthrough, jeśli runtime XR to obsługuje",
|
|
||||||
"SCREEN_RENDER_DOWN_HELP": "Pomaga redukować aliasing na ekranach o wysokiej rozdzielczości",
|
|
||||||
"ENABLE_WATCH": "Włącz zegarek",
|
|
||||||
"SETS_ON_WATCH": "Lista zestawów na zegarku",
|
|
||||||
"TROUBLESHOOTING": "Rozwiązywanie problemów",
|
|
||||||
"CLEAR_SAVED_STATE": "Wyczyść zapisany stan",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "Wyczyść tokeny PipeWire",
|
|
||||||
"DELETE_ALL_CONFIGS": "Wyczyść konfigurację",
|
|
||||||
"RESTART_SOFTWARE": "Restartuj WayVR",
|
|
||||||
"CLEAR_SAVED_STATE_HELP": "Zresetuj zestawy i pozycje nakładek",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "Zapytaj o wybór ekranu przy następnym uruchomieniu",
|
|
||||||
"DELETE_ALL_CONFIGS_HELP": "Usuń wszystkie pliki konfiguracyjne z katalogu conf.d",
|
|
||||||
"RESTART_SOFTWARE_HELP": "Zastosuj ustawienia wymagające ponownego uruchomienia",
|
|
||||||
"CAPTURE_METHOD": "Przechwytywanie ekranu Wayland",
|
|
||||||
"CAPTURE_METHOD_HELP": "Spróbuj zmienić tę opcję, jeśli masz\nproblemy z czarnym lub migoczącym ekranem",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK": "Środkowy przycisk myszy na klawiaturze",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK_HELP": "Modyfikator, który ma zostać użyty podczas pisania\nfioletową wiązką lasera",
|
|
||||||
"OPTION": {
|
|
||||||
"AUTO": "Automatycznie",
|
|
||||||
"AUTO_HELP": "Skopiuj ekran za pomocą GPU, jeśli obsługiwane,\nw przeciwnym razie GPU PipeWire.",
|
|
||||||
"PIPEWIRE_HELP": "Szybkie przechwytywanie GPU,\nstandard na wszystkich komputerach.",
|
|
||||||
"PW_FALLBACK_HELP": "Powolna metoda z wysokim użyciem procesora.\nWypróbuj w przypadku, gdy PipeWire GPU nie działa",
|
|
||||||
"SCREENCOPY_GPU_HELP": "Szybkie działanie, brak wyskakujących okien z informacją o udostępnianiu ekranu.\nDziała na: Hyprland, Niri, River, Sway",
|
|
||||||
"SCREENCOPY_HELP": "Wolne, bez wyskakujących okienek udostępniania ekranu.\nDziała na: Hyprland, Niri, River, Sway",
|
|
||||||
"NONE": "Brak",
|
|
||||||
"HMD_PINCH": "HMD + ściśnięcie placami",
|
|
||||||
"EYE_PINCH": "Ściśnięcie palcami + oko",
|
|
||||||
"EYE_ONLY": "Tylko oko",
|
|
||||||
"HMD_ONLY": "Tylko HMD",
|
|
||||||
"NONE_INPUT_HELP": "Nie emuluj myszy ani klawiatury.\nBrak możliwości interakcji z ekranami.",
|
|
||||||
"UINPUT": "Emulacja urządzenia",
|
|
||||||
"UINPUT_HELP": "Używa modułu uinput do emulowania urządzenia.\nTwoje konto użytkownika musi należeć do grupy input.\nWiadomo, że działa dobrze na większości komputerów stacjonarnych.",
|
|
||||||
"WL_VIRTUAL": "Wirtualne wejście Wayland",
|
|
||||||
"WL_VIRTUAL_HELP": "Wysyłaj wejście myszki/klawiatury do kompozytora Wayland za pomocą\nzwlr_virtual_pointer i zwp_virtual_keyboard.\nDziała niezawodnie tylko na niektórych pulpitach.\nNIE działa na KDE, GNOME ani COSMIC."
|
|
||||||
},
|
|
||||||
"AUTOSTART_APPS": "Aplikacje auto-start",
|
|
||||||
"HANDSFREE_POINTER": "Tryb bez użycia rąk",
|
|
||||||
"HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie.",
|
|
||||||
"UI_GRADIENT_INTENSITY": "Intensywność gradientu UI",
|
|
||||||
"RESET_PLAYSPACE": "Zresetuj przestrzeń gry",
|
|
||||||
"RESET_PLAYSPACE_HELP": "Wyczyść przesunięcie przestrzeni gry.",
|
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION": "Blokuj pozy podczas interakcji z klawiaturą",
|
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blokuje odbieranie póz przez grę, gdy kursor myszy znajduje się nad klawiaturą i włączona jest opcja 'Blokuj dane wejściowe z gry'",
|
|
||||||
"LANGUAGE": "Język",
|
|
||||||
"REQUIRES_RESTART": "Wymaga restartu",
|
|
||||||
"MISC": "Różne",
|
|
||||||
"GRID_OPACITY": "Przezroczystość siatki podłogowej",
|
|
||||||
"GRID_OPACITY_HELP": "Przezroczystość siatki podłogowej, gdy włączony jest skybox",
|
|
||||||
"BROWSE_ONLINE_CATALOG": "Przeglądaj katalog online...",
|
|
||||||
"BROWSE_SKYMAPS": "Przeglądaj skymaps",
|
|
||||||
"COLOR_KEYING": "Kluczowanie kolorem",
|
|
||||||
"NO_SKYMAPS_FOUND": "Nie znaleziono skymap",
|
|
||||||
"SELECT_VARIANT": "Wybierz wariant",
|
|
||||||
"SHOW_WELCOME_SCREEN": "Pokaż ekran powitalny",
|
|
||||||
"SKYBOX": "Skymap",
|
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "Ta skymapa została już pobrana. Wybierz żądaną akcję.",
|
|
||||||
"WATCH_VIEW_ANGLE": "Kąty widzenia Watch",
|
|
||||||
"WATCH_VIEW_ANGLE_HELP": "Kontroluj, jak zegarek zanika",
|
|
||||||
"BINDINGS": {
|
"BINDINGS": {
|
||||||
"COMP": {
|
"COMP": {
|
||||||
"CLICK": "Kliknięcie",
|
"CLICK": "Kliknięcie",
|
||||||
"FORCE": "Siła",
|
"FORCE": "Siła nacisku",
|
||||||
"TOUCH": "Dotyk",
|
"TOUCH": "Dotknięcie",
|
||||||
"VALUE": "Wartość",
|
"VALUE": "Wartość",
|
||||||
"PROXIMITY": "Bliskość",
|
"PROXIMITY": "Bliskość",
|
||||||
"X_AXIS": "Oś X",
|
"X_AXIS": "Oś X",
|
||||||
|
|
@ -112,20 +58,20 @@
|
||||||
},
|
},
|
||||||
"TYPE": {
|
"TYPE": {
|
||||||
"BUMPER": "Bumper",
|
"BUMPER": "Bumper",
|
||||||
"DPAD_UP": "D-pad w górę",
|
"DPAD_UP": "D-pad góra",
|
||||||
"DPAD_DOWN": "D-pad w dół",
|
"DPAD_DOWN": "D-pad dół",
|
||||||
"DPAD_LEFT": "D-pad w lewo",
|
"DPAD_LEFT": "D-pad lewo",
|
||||||
"DPAD_RIGHT": "D-pad w prawo",
|
"DPAD_RIGHT": "D-pad prawo",
|
||||||
"JOYSTICK": "Joystick",
|
"JOYSTICK": "Drążek",
|
||||||
"MENU": "Menu",
|
"MENU": "Menu",
|
||||||
"SHOULDER": "Boczny przycisk",
|
"SHOULDER": "Ramiona",
|
||||||
"SQUEEZE": "Chwyt",
|
"SQUEEZE": "Chwyt",
|
||||||
"SYSTEM": "System",
|
"SYSTEM": "System",
|
||||||
"THUMBREST": "Thumbrest",
|
"THUMBREST": "Podpora kciuka",
|
||||||
"THUMBSTICK": "Thumbstick",
|
"THUMBSTICK": "Thumbstick",
|
||||||
"TRACKPAD": "Trackpad",
|
"TRACKPAD": "Gładzik",
|
||||||
"TRIGGER": "Spust",
|
"TRIGGER": "Spust",
|
||||||
"VIEW": "Widok"
|
"VIEW": "View"
|
||||||
},
|
},
|
||||||
"CLICK": {
|
"CLICK": {
|
||||||
"ANY": "Dowolny",
|
"ANY": "Dowolny",
|
||||||
|
|
@ -135,166 +81,269 @@
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"CLICK": "Kliknięcie*",
|
"CLICK": "Kliknięcie*",
|
||||||
"GRAB": "Chwyć*",
|
"GRAB": "Chwytanie*",
|
||||||
"ALT_CLICK": "Własne polecenie shell exec (ustaw alt_click w konfiguracji)",
|
"ALT_CLICK": "Własna komenda shell (ustaw alt_click w konfiguracji)",
|
||||||
"SHOW_HIDE": "Pokaż, ukryj, wycentruj ponownie*",
|
"SHOW_HIDE": "Pokaż, ukryj, wycentruj*",
|
||||||
"TOGGLE_DASHBOARD": "Przełącz dashboard",
|
"TOGGLE_DASHBOARD": "Przełącz pulpit",
|
||||||
"SPACE_DRAG": "Przesuwanie Playspace",
|
"SPACE_DRAG": "Przeciąganie przestrzeni gry",
|
||||||
"SPACE_ROTATE": "Obrót Playspace",
|
"SPACE_ROTATE": "Obrót przestrzeni gry",
|
||||||
"SPACE_RESET": "Resetowanie playspace",
|
"SPACE_RESET": "Reset przestrzeni gry",
|
||||||
"CLICK_MODIFIER_RIGHT": "Modyfikator prawego kliknięcia",
|
"CLICK_MODIFIER_RIGHT": "Modyfikator prawego kliknięcia",
|
||||||
"CLICK_MODIFIER_MIDDLE": "Modyfikator środkowego kliknięcia",
|
"CLICK_MODIFIER_MIDDLE": "Modyfikator środkowego przycisku myszy",
|
||||||
"MOVE_MOUSE": "Ruszaj myszą (jeśli domyślnie wyłączone)",
|
"MOVE_MOUSE": "Przesuń mysz (jeśli domyślnie wyłączona)",
|
||||||
"SCROLL": "Przewijanie*"
|
"SCROLL": "Przewijanie*"
|
||||||
},
|
},
|
||||||
"LEFT": "Lewy",
|
"LEFT": "Lewy",
|
||||||
"RIGHT": "Prawy",
|
"RIGHT": "Prawy",
|
||||||
"COMPONENT": "Typ aktywacji",
|
"COMPONENT": "Typ aktywacji",
|
||||||
"SUBPATH": "Sterowanie aktywacją",
|
"SUBPATH": "Aktywujący sterownik",
|
||||||
"THRESHOLD": "Aktywuj po przekroczeniu górnej wartości\nDezaktywuj po spadku poniżej dolnej wartości"
|
"THRESHOLD": "Aktywuj powyżej górnej wartości\nDeaktywuj poniżej dolnej wartości"
|
||||||
},
|
},
|
||||||
|
"BROWSE_ONLINE_CATALOG": "Przeglądaj katalog online...",
|
||||||
|
"BROWSE_SKYMAPS": "Przeglądaj skymapy",
|
||||||
|
"CAPTURE_METHOD": "Metoda przechwytywania ekranu",
|
||||||
|
"CAPTURE_METHOD_HELP": "Spróbuj zmienić tę opcję, jeśli \nekran jest czarny lub migocze",
|
||||||
|
"COLOR_KEYING": "Kluczowanie koloru",
|
||||||
|
"COLOR_PALETTE": "Paleta kolorów",
|
||||||
|
"COLOR_PALETTE_HELP": "Kliknij, aby przeglądać palety kolorów.\nAby stworzyć własne, odwiedź stronę internetową!",
|
||||||
|
"COLOR_PALETTES": "Palety kolorów",
|
||||||
|
"COLOR_PALETTE_CURRENT": "Aktualnie aktywny motyw.",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Dodaj własny motyw!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Kliknij, aby otworzyć podręcznik online.",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS": "Wyczyść tokeny PipeWire",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "Zapytaj o wybór ekranu przy następnym uruchomieniu",
|
||||||
|
"CLEAR_SAVED_STATE": "Wyczyść zapisany stan",
|
||||||
|
"CLEAR_SAVED_STATE_HELP": "Zresetuj zestawy i pozycje nakładek",
|
||||||
|
"CLICK_FREEZE_TIME_MS": "Czas zamrożenia kliknięcia (ms)",
|
||||||
|
"CLICK_FREEZE_TIME_MS_HELP": "Ułatwia precyzję dwukliku",
|
||||||
|
"CLOCK_12H": "Zegar 12-godzinny",
|
||||||
|
"CONTROLS": "Sterowanie",
|
||||||
|
"DELETE_ALL_CONFIGS": "Wyczyść konfigurację",
|
||||||
|
"DELETE_ALL_CONFIGS_HELP": "Usuń wszystkie pliki konfiguracyjne z conf.d",
|
||||||
|
"DOUBLE_CURSOR_FIX": "Poprawka podwójnego kursora",
|
||||||
|
"DOUBLE_CURSOR_FIX_HELP": "Włącz, jeśli widzisz dwa kursory",
|
||||||
|
"DEFAULT_OVERLAY_SCALE": "Domyślny rozmiar nakładki",
|
||||||
|
"DEFAULT_OVERLAY_SCALE_HELP": "Twórz nowe nakładki w tej skali.",
|
||||||
|
"DEFAULT_CURVATURE": "Domyślna krzywizna nakładki",
|
||||||
|
"DEFAULT_OPACITY": "Domyślna przezroczystość nakładki",
|
||||||
|
"DEFAULT_POSITIONING": "Domyślne pozycjonowanie nakładki",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "Dotyczy tylko nowych nakładek",
|
||||||
"ENABLED": "Włączone",
|
"ENABLED": "Włączone",
|
||||||
|
"FEATURES": "Funkcje",
|
||||||
|
"FOCUS_FOLLOWS_MOUSE_MODE": "Kursor podąża za spustem",
|
||||||
|
"HANDSFREE_POINTER": "Tryb bezkontaktowy",
|
||||||
|
"HANDSFREE_POINTER_HELP": "Metoda sterowania, gdy kontrolery ruchu są niedostępne.\nLewy chwyt to przeciąganie, prawy to kliknięcie.",
|
||||||
|
"HANDSFREE_ALT_TAB": "Kierowanie przełącznikiem aplikacji",
|
||||||
|
"HANDSFREE_ALT_TAB_HELP": "Przytrzymaj Super+X, wyceluj w wybrane okno, a następnie puść, aby zmienić focus.",
|
||||||
|
"HIDE_GRAB_HELP": "Ukryj pomoc chwytania",
|
||||||
|
"HIDE_USERNAME": "Ukryj nazwę użytkownika",
|
||||||
"INPUT_EMULATION_METHOD": "Metoda emulacji wejścia",
|
"INPUT_EMULATION_METHOD": "Metoda emulacji wejścia",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "Spróbuj zmienić tę opcję w przypadku, gdy wejście myszy lub\nklawiatury nie jest rejestrowane.",
|
"INPUT_EMULATION_METHOD_HELP": "Zmień tę opcję, jeśli wejście z myszy lub \nklawiatury nie jest rejestrowane.",
|
||||||
"INPUT_PROFILES": "Zmień klawiszologię",
|
"INPUT_CAPTURE_METHOD": "Metoda przechwytywania wejścia",
|
||||||
"INPUT_PROFILES_HELP": "Przypisania przycisków kontrolera OpenXR",
|
"INPUT_CAPTURE_METHOD_HELP": "Pozwala na korzystanie z fizycznych urządzeń wejściowych w WayVR.\n Super+Z: Przełącz sterowanie między WayVR a prawdziwym pulpitem\n Super+X: Przełączaj aplikacje WayVR",
|
||||||
|
"INPUT_PROFILES": "Zmień mapowanie przycisków",
|
||||||
|
"INPUT_PROFILES_HELP": "Mapowanie przycisków kontrolera OpenXR",
|
||||||
|
"INVERT_SCROLL_DIRECTION_X": "Odwróć kierunek przewijania w poziomie",
|
||||||
|
"INVERT_SCROLL_DIRECTION_Y": "Odwróć kierunek przewijania w pionie",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK": "Środkowy przycisk myszy (klawiatura)",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK_HELP": "Modyfikator używany podczas\npisania fioletowym laserem",
|
||||||
|
"KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury",
|
||||||
|
"LANGUAGE": "Język",
|
||||||
|
"LEFT_HANDED_MOUSE": "Mysz dla leworęcznych",
|
||||||
|
"LEFT_HANDED_MOUSE_HELP": "Użyj, jeśli przyciski myszy są zamienione",
|
||||||
|
"LONG_PRESS_DURATION": "Czas przytrzymania",
|
||||||
|
"LOOK_AND_FEEL": "Wygląd i styl",
|
||||||
|
"MISC": "Różnorodne",
|
||||||
|
"NOTIFICATIONS_ENABLED": "Włącz powiadomienia",
|
||||||
|
"NOTIFICATIONS_SOUND_ENABLED": "Dźwięki powiadomień",
|
||||||
"NOT_SUPPORTED": "Nieobsługiwane",
|
"NOT_SUPPORTED": "Nieobsługiwane",
|
||||||
"SPACE_DRAG": "Space-drag",
|
"NO_SKYMAPS_FOUND": "Nie znaleziono skymapów",
|
||||||
"SPACE_GRAVITY_DAMPING": "Spowalnianie",
|
"OPAQUE_BACKGROUND": "Nieprzezroczyste tło",
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "Sztuczne spowalnianie mające na celu zatrzymywanie ruchu po pewnym czasie. 0.1 - wysokie spowolnienie, 1.0 - brak spowolnienia",
|
"OPTION": {
|
||||||
|
"ANCHORED_HELP": "Porusza się wraz z markerem środka. Zalecane.",
|
||||||
|
"FLOATING_HELP": "Przesuwa się niezależnie, centruje ponownie.\nŁatwo go zgubić; niezalecane.",
|
||||||
|
"STATIC_HELP": "Pozostaje w stałym miejscu względem świata.",
|
||||||
|
"AUTO": "Automatycznie",
|
||||||
|
"AUTO_HELP": "ScreenCopy GPU (jeśli wspierane),\nw przeciwnym razie PipeWire GPU.",
|
||||||
|
"EYE_ONLY": "Laser z oczu",
|
||||||
|
"EYE_PINCH": "Wzrok + szczypnięcie",
|
||||||
|
"HMD_ONLY": "Laser HMD",
|
||||||
|
"HMD_PINCH": "HMD + szczypnięcie",
|
||||||
|
"NONE": "Brak",
|
||||||
|
"NONE_INPUT_HELP": "Nie emuluj myszy i klawiatury.\nInterakcja z ekranami będzie niemożliwa.",
|
||||||
|
"NONE_INPUT_CAPTURE_HELP": "Nie przechwytuj myszy i klawiatury.\nBrak możliwości korzystania z fizycznej myszy lub\nklawiatury w aplikacjach uruchomionych w WayVR.",
|
||||||
|
"PIPEWIRE_HELP": "Szybkie przechwytywanie obrazu z GPU,\nstandard na wszystkich pulpitach.",
|
||||||
|
"PW_FALLBACK_HELP": "Powolna metoda z dużym obciążeniem procesora.\nWypróbuj, jeśli PipeWire GPU nie działa.",
|
||||||
|
"SCREENCOPY_GPU_HELP": "Szybka metoda, bez wyskakujących okien udostępniania ekranu.\nDziała w: Hyprland, Niri, River, Sway",
|
||||||
|
"SCREENCOPY_HELP": "Powolne, bez wyskakujących okien udostępniania ekranu.\nDziała na: Hyprland, Niri, River, Sway",
|
||||||
|
"UINPUT": "Emulacja urządzenia",
|
||||||
|
"UINPUT_HELP": "Wykorzystuje moduł uinput do emulacji urządzenia.\nSprawdzone i działa dobrze na większości systemów desktopowych.",
|
||||||
|
"EVDEV_HELP": "Przejmij urządzenia wejściowe na wyłączność.\nUżytkownik musi należeć do grupy input.",
|
||||||
|
"WL_VIRTUAL": "Wirtualny input Wayland",
|
||||||
|
"WL_VIRTUAL_HELP": "Wysyłaj zdarzenia do kompozytora Wayland za pomocą\nzwlr_virtual_pointer i zwp_virtual_keyboard.\nDziała stabilnie tylko w niektórych środowiskach.\nNIE działa w KDE, GNOME ani COSMIC."
|
||||||
|
},
|
||||||
|
"POINTER_ACCELERATION": "Przyspieszenie myszy",
|
||||||
|
"POINTER_ACCELERATION_HELP": "Wł.: Adaptacyjne przyspieszenie myszy\nWył.: Stała prędkość",
|
||||||
|
"POINTER_LERP_FACTOR": "Wygładzanie wskaźnika",
|
||||||
|
"POINTER_SPEED": "Prędkość myszy",
|
||||||
|
"REQUIRES_RESTART": "Wymaga restartu",
|
||||||
|
"RESET_PLAYSPACE": "Resetuj przestrzeń gry",
|
||||||
|
"RESET_PLAYSPACE_HELP": "Wyczyść przesunięcie przestrzeni gry.",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "Zapisz środek przestrzeni gry",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "Użyj aktualnej przestrzeni gry dla przypisania resetowania przestrzeni.",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "Zresetuj centrum przestrzeni gry",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "Resetuj aktualny środek przestrzeni gry.",
|
||||||
|
"RESTART_SOFTWARE": "Uruchom ponownie program",
|
||||||
|
"RESTART_SOFTWARE_HELP": "Zastosuj ustawienia wymagające restartu",
|
||||||
|
"ROUND_MULTIPLIER": "Zaokrąglenie krawędzi UI",
|
||||||
|
"SCREEN_RENDER_DOWN": "Renderuj ekran w niższej rozdzielczości",
|
||||||
|
"SCREEN_RENDER_DOWN_HELP": "Pomaga zredukować aliasing na ekranach o wysokiej rozdzielczości",
|
||||||
|
"SCROLL_SPEED": "Prędkość przewijania",
|
||||||
|
"SELECT_VARIANT": "Wybierz wariant",
|
||||||
|
"SNAP_ANGLE_DEG": "Kąt przyciągania pochylenia i obrotu okna",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "Chwycone okna przyciągają się do tego kąta na osi pochylenia i obrotu.",
|
||||||
|
"ENABLE_WATCH": "Włącz zegarek",
|
||||||
|
"SETS_ON_WATCH": "Zestawy na zegarku",
|
||||||
|
"SHOW_WELCOME_SCREEN": "Pokaż ekran powitalny",
|
||||||
|
"SKYBOX": "Skymap",
|
||||||
|
"SKYMAP_ALREADY_DOWNLOADED": "Ta skymapa jest już pobrana. Wybierz żądaną akcję.",
|
||||||
|
"SPACE_DRAG": "Przestrzeń gry",
|
||||||
|
"SPACE_DRAG_MULTIPLIER": "Mnożnik przesuwania w przestrzeni",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "Pozostaw nakładki podczas przesuwania przestrzeni gry",
|
||||||
|
"SPACE_DRAG_UNLOCKED": "Pozwól na przesuwanie w przestrzeni we wszystkich osiach",
|
||||||
|
"SPACE_GRAVITY_DAMPING": "Opór",
|
||||||
|
"SPACE_GRAVITY_DAMPING_HELP": "Sztuczny opór spowalniający ruch. 0,1 – duży opór, 1,0 – brak oporu",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH": "Siła wyrzutu",
|
"SPACE_GRAVITY_FLING_STRENGTH": "Siła wyrzutu",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Mnożnik intensywności siły grawitacyjnego wyrzutu po użyciu funkcji space-drag.\n0.0 - brak ruchu, 2.0 - podwójna intensywność",
|
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Mnożnik intensywności siły wyrzutu grawitacyjnego po Space-dragu.\n0.0 - brak ruchu, 2.0 - podwójna intensywność",
|
||||||
"SPACE_GRAVITY_GRAVITY": "Grawitacja",
|
"SPACE_GRAVITY_GRAVITY": "Grawitacja",
|
||||||
"SPACE_GRAVITY_GRAVITY_HELP": "Wielkość siły działającej w dół. 0.0 - brak grawitacji",
|
"SPACE_GRAVITY_GRAVITY_HELP": "Siła przyciągania w dół. 0.0 - brak grawitacji",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION": "Tarcie podłoża",
|
"SPACE_GRAVITY_GROUND_FRICTION": "Tarcie o podłoże",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Moc tarcia spowalniającego Cię podczas kontaktu z podłożem.\n0.0 - brak tarcia (jak na lodzie), 1.0 - chropowata powierzchnia",
|
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Wartość tarcia spowalniającego ruch przy kontakcie z podłożem.\n0.0 - brak tarcia (jak na lodzie), 1.0 - chropowata powierzchnia",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "Wysokość podłogi",
|
"SPACE_GRAVITY_FLOOR_HEIGHT": "Wysokość podłogi",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Pozycja Y, w której znajduje się podłoga. Grawitacja przestaje działać po osiągnięciu tej wysokości.",
|
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Pozycja Y podłogi. Grawitacja zatrzymuje się na tej wysokości.",
|
||||||
"SAVE": "Zapisz",
|
"SPACE_ROTATE_UNLOCKED": "Pozwól na obrót przestrzeni gry we wszystkich osiach",
|
||||||
"CANCEL": "Anuluj",
|
"TROUBLESHOOTING": "Rozwiązywanie problemów",
|
||||||
|
"UI_GRADIENT_INTENSITY": "Intensywność gradientu UI",
|
||||||
|
"UPRIGHT_SCREEN_FIX": "Korekta pionowego ekranu",
|
||||||
|
"UPRIGHT_SCREEN_FIX_HELP": "Naprawia pionowe ekrany na niektórych pulpitach",
|
||||||
|
"USE_PASSTHROUGH": "Włącz passthrough",
|
||||||
|
"USE_PASSTHROUGH_HELP": "Włącz passthrough, jeśli środowisko XR je obsługuje",
|
||||||
|
"USE_SKYBOX": "Pokaż skymap",
|
||||||
|
"USE_SKYBOX_HELP": "Wyświetl skymap, gdy nie ma uruchomionej aplikacji sceny lub trybu passthrough",
|
||||||
|
"WATCH_VIEW_ANGLE": "Kąty widzenia zegarka",
|
||||||
|
"WATCH_VIEW_ANGLE_HELP": "Steruj tym, jak zegarek znika",
|
||||||
"WHISPER": {
|
"WHISPER": {
|
||||||
"NEED_TO_DOWNLOAD_MODEL": "Wybrany model musi zostać pobrany.\nPobrać go teraz?",
|
"NEED_TO_DOWNLOAD_MODEL": "Wybrany model musi zostać pobrany.\nPobrać go teraz?",
|
||||||
"REMOVE_UNUSED_MODELS": "Wyłączasz funkcję zamiany mowy na tekst.\nCzy chcesz usunąć pobrane modele Whisper, aby zwolnić miejsce?"
|
"REMOVE_UNUSED_MODELS": "Wyłączasz funkcję zamiany mowy na tekst.\nCzy chcesz usunąć pobrane modele Whisper, aby zwolnić miejsce?"
|
||||||
},
|
},
|
||||||
"WHISPER_MODEL": "Model mowy na tekst",
|
"WHISPER_MODEL": "Model mowy na tekst",
|
||||||
"WHISPER_MODEL_HELP": "Model Whisper do wykorzystania.\nWiększe modele dają dokładniejsze\nwyniki, ale zużywają więcej pamięci VRAM."
|
"WHISPER_MODEL_HELP": "Model Whisper do użycia.\nWiększe modele dają dokładniejsze\nwyniki, ale zużywają więcej pamięci VRAM.",
|
||||||
|
"GRID_OPACITY": "Przezroczystość siatki podłogi",
|
||||||
|
"GRID_OPACITY_HELP": "Przezroczystość siatki podłogi przy włączonym Skymapie",
|
||||||
|
"XWAYLAND_BY_DEFAULT": "Uruchamiaj aplikacje domyślnie w trybie kompatybilności",
|
||||||
|
"SAVE": "Zapisz",
|
||||||
|
"CANCEL": "Anuluj"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
"APPLICATION_LAUNCHER": "Launcher aplikacji",
|
||||||
|
"APPLICATION_STARTED": "Uruchomiono aplikację",
|
||||||
"APPLICATIONS": "Aplikacje",
|
"APPLICATIONS": "Aplikacje",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
"AUTO_SWITCH_TO_VR_AUDIO": "Automatyczne przełączanie na dźwięk VR",
|
"AUTO_SWITCH_TO_VR_AUDIO": "Auto-przełączanie na dźwięk VR",
|
||||||
"CARDS": "Karty",
|
"CARDS": "Karty dźwiękowe",
|
||||||
"FAILED_TO_SWITCH_MICROPHONE": "Nie udało się przełączyć mikrofon",
|
"FAILED_TO_SWITCH_MICROPHONE": "Błąd przełączania mikrofonu",
|
||||||
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon ustawiono pomyślnie",
|
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon ustawiony pomyślnie",
|
||||||
"MICROPHONES": "Mikrofony",
|
"MICROPHONES": "Mikrofony",
|
||||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Brak mikrofonu VR. Włącz go ręcznie.",
|
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Nie znaleziono mikrofonu VR. Przełącz go ręcznie.",
|
||||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Brak głośników VR. Włącz je ręcznie.",
|
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Nie znaleziono głośników VR. Przełącz je ręcznie.",
|
||||||
"SELECT_AUDIO_CARD_PROFILE": "Wybierz profil karty dźwiękowej",
|
"SELECT_AUDIO_CARD_PROFILE": "Wybierz profil karty dźwiękowej",
|
||||||
"SETTINGS": "Ustawienia dźwięku",
|
"SETTINGS": "Ustawienia dźwięku",
|
||||||
"SPEAKERS": "Głośniki",
|
"SPEAKERS": "Głośniki",
|
||||||
"SPEAKERS_SET_SUCCESSFULLY": "Głośniki ustawiono pomyślnie",
|
"SPEAKERS_SET_SUCCESSFULLY": "Głośniki ustawione pomyślnie",
|
||||||
"VOLUME": "Głośność"
|
"VOLUME": "Głośność"
|
||||||
},
|
},
|
||||||
|
"CLOSE_WINDOW": "Zamknij okno",
|
||||||
|
"CREATION_DATE": "Data utworzenia",
|
||||||
|
"DEBUG_INFO": "Informacje diagnostyczne",
|
||||||
|
"DISPLAY_BRIGHTNESS": "Jasność ekranu",
|
||||||
|
"DONATE": {
|
||||||
|
"SUPPORT_US": "Wesprzyj nas",
|
||||||
|
"DESCRIPTION": "Jesteśmy małym zespołem dwóch programistów, którzy tworzą WayVR w wolnym czasie. Jeśli lubisz korzystać z tego programu, rozważ wsparcie nas finansowo – każda darowizna pomaga nam działać dalej.",
|
||||||
|
"THANK_YOU_WAYVR": "Dzięki od zespołu WayVR!",
|
||||||
|
"BUTTON_TOOLTIP": "Wesprzyj projekt przez Open Collective",
|
||||||
|
"CURRENT_SUPPORTERS": "Obecni darczyńcy",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Wspierane przez {USER}|Dzięki dla {USER}|Sponsor: {USER}|Z pomocą {USER}|Wkład od {USER}|Umożliwione przez {USER}|Dzięki wsparciu {USER}|Patron: {USER}|Działamy dzięki {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kawa od {USER}|Energia dostarczona przez {USER}|Wielkie brawa dla {USER}!|Dzięki {USER} idziemy do przodu|Razem z {USER} rośniemy w siłę|Serwery napędzane przez {USER}|Z ogromną wdzięcznością dla {USER}|Napędzane przez {USER}|Wsparcie od przyjaciół takich jak {USER}",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Wspierane przez legendę: {USER}|Dostawa kofeiny od {USER}|Prawdziwa legenda: {USER}|Gwiazda dnia: {USER}|Absolutna supergwiazda: {USER}|Opłaca rachunki za prąd: {USER}|Ludzie, którzy czynią to możliwe: {USER}|Sponsor spokoju ducha: {USER}|Konwerter kawy na kod: {USER}|Strażnik stabilności produkcji: {USER}|Jedyny w swoim rodzaju: {USER}|Przesyła bufory dmabuf: {USER}"
|
||||||
|
},
|
||||||
|
"DOWNLOAD": "Pobierz",
|
||||||
|
"DOWNLOADER": "Menedżer pobierania",
|
||||||
|
"WELCOME": {
|
||||||
|
"ALL_SET": "Wszystko gotowe!",
|
||||||
|
"BASICS": "Te podstawy pozwolą Ci z łatwością zacząć korzystać z WayVR.",
|
||||||
|
"CENTER_MARKER": "Znacznik środkowy pojawi się przed Tobą podczas centrowania. Rozmieść wokół niego nakładki!",
|
||||||
|
"DOUBLE_PRESS_TO_TOGGLE": "Dwukrotnie naciśnij B (na Index) lub Y (na Meta), aby wyświetlić, wycentrować lub ukryć swój zestaw. Wypróbuj teraz.",
|
||||||
|
"FEATURES_DOCUMENTATION": "Istnieje wiele innych funkcji wartych dostosowania. Więcej informacji znajdziesz w dokumentacji pod adresem",
|
||||||
|
"FINISH_TUTORIAL": "Zakończ samouczek",
|
||||||
|
"GRAB_BOTH_HANDS": "Chwyć oburącz, aby przesunąć konkretny element zestawu.",
|
||||||
|
"GRAB_ONE_HAND": "Chwyć go jedną ręką, aby przesunąć zestaw.",
|
||||||
|
"GREETING": "Cześć!",
|
||||||
|
"GUIDE_INTRO": "Przeprowadźmy Cię przez pierwsze kroki.",
|
||||||
|
"LASER_COLORS": "Kolory laserów",
|
||||||
|
"LASER_FUNCTIONALITY": "Wiele funkcji WayVR zależy od koloru lasera użytego do interakcji z elementem UI. Nie musisz naciskać tych przycisków – wystarczy ich dotknąć!",
|
||||||
|
"LAST_PAGE_INFO": "Ten samouczek przestanie się wyświetlać po dotarciu do ostatniej strony.",
|
||||||
|
"LOOK_AT_LEFT_WRIST": "Spójrz na lewy nadgarstek. To twój zegarek.",
|
||||||
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Tryb środkowego kliknięcia: Purpurowy laser",
|
||||||
|
"MOVING_YOUR_SET": "Przesuwanie zestawu",
|
||||||
|
"NEXT_BUTTON": "Naciśnij przycisk Dalej poniżej, aby zacząć.",
|
||||||
|
"REGULAR_MODE_BLUE_LASER": "Tryb standardowy: Niebieski laser",
|
||||||
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Przesuń to okno, używając przycisku chwytu kontrolera.",
|
||||||
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "Tryb prawego kliknięcia: Pomarańczowy laser",
|
||||||
|
"THANKS_FOR_INSTALLING": "Dzięki za zainstalowanie WayVR!",
|
||||||
|
"WATCH": "Zegarek",
|
||||||
|
"WORKING_SET": "Aktywny zestaw"
|
||||||
|
},
|
||||||
|
"DOWNLOAD_AGAIN": "Pobierz ponownie",
|
||||||
|
"DOWNLOADING_FILE": "Pobieranie pliku...",
|
||||||
|
"FAILED_TO_LAUNCH_APPLICATION": "Błąd uruchamiania aplikacji:",
|
||||||
|
"GAME_LAUNCHED": "Gra uruchomiona",
|
||||||
|
"GAME_LIST": {
|
||||||
|
"NO_GAMES_FOUND": "Nie znaleziono gier",
|
||||||
|
"RUNNING_GAMES_LIST": "Lista uruchomionych gier"
|
||||||
|
},
|
||||||
"GAMES": "Gry",
|
"GAMES": "Gry",
|
||||||
"GENERAL_SETTINGS": "Ustawienia ogólne",
|
"GENERAL_SETTINGS": "Ustawienia ogólne",
|
||||||
|
"GETTING_STARTED": "Pierwsze kroki",
|
||||||
"HEIGHT": "Wysokość",
|
"HEIGHT": "Wysokość",
|
||||||
"HELLO": "Witaj!",
|
"HELLO": "Witaj!",
|
||||||
"HELLO_USER": "Witaj, {USER}!",
|
"HELLO_USER": "Witaj, {USER}!",
|
||||||
"HIDE": "Ukryj",
|
"HIDE": "Ukryj",
|
||||||
"HOME_SCREEN": "Ekran główny",
|
"HOME_SCREEN": "Ekran główny",
|
||||||
|
"MODIFICATION_DATE": "Data modyfikacji",
|
||||||
"MONADO_RUNTIME": "Środowisko Monado",
|
"MONADO_RUNTIME": "Środowisko Monado",
|
||||||
|
"LOADING": "Ładowanie...",
|
||||||
"POPUP_ADD_DISPLAY": {
|
"POPUP_ADD_DISPLAY": {
|
||||||
"RESOLUTION": "Rozdzielczość"
|
"RESOLUTION": "Rozdzielczość"
|
||||||
},
|
},
|
||||||
"REMOVE": "Usuń",
|
"PROCESS": {
|
||||||
"SETTINGS": "Ustawienia",
|
"FORCE_KILL": "Wymuś zamknięcie",
|
||||||
"SHOW": "Pokaż",
|
"STOP": "Zatrzymaj"
|
||||||
"WIDTH": "Szerokość",
|
|
||||||
"FAILED_TO_LAUNCH_APPLICATION": "Nie udało się uruchomić aplikacji:",
|
|
||||||
"APPLICATION_STARTED": "Aplikacja uruchomiona",
|
|
||||||
"CLOSE_WINDOW": "Zamknij okno",
|
|
||||||
"GAME_LIST": {
|
|
||||||
"NO_GAMES_FOUND": "Nie znaleziono gier",
|
|
||||||
"RUNNING_GAMES_LIST": "Lista uruchomionych gier"
|
|
||||||
},
|
},
|
||||||
"TERMINATE_PROCESS": "Zakończ proces",
|
|
||||||
"GAME_LAUNCHED": "Gra uruchomiona",
|
|
||||||
"APP_LAUNCHER": {
|
|
||||||
"MODE": {
|
|
||||||
"NATIVE": "Tryb natywny",
|
|
||||||
"CAGE": "Tryb kompatybilności (Cage)"
|
|
||||||
},
|
|
||||||
"RES_TITLE": "Rozdzielczość",
|
|
||||||
"ASPECT_TITLE": "Proporcje",
|
|
||||||
"ASPECT": {
|
|
||||||
"WIDE": "Szeroki",
|
|
||||||
"SEMI_WIDE": "Półszeroki",
|
|
||||||
"SQUARE": "Kwadrat",
|
|
||||||
"SEMI_TALL": "Pół-wysoki",
|
|
||||||
"TALL": "Wysoki"
|
|
||||||
},
|
|
||||||
"POS_TITLE": "Pozycjonowanie",
|
|
||||||
"POS": {
|
|
||||||
"FLOATING": "Pływający",
|
|
||||||
"ANCHORED": "Przymocowane",
|
|
||||||
"STATIC": "Statyczny",
|
|
||||||
"FLOATING_HELP": "Porusza się niezależnie, wycentrowuje się po otwarciu.",
|
|
||||||
"ANCHORED_HELP": "Pozostaje nieruchoma względem centralnego znacznika.",
|
|
||||||
"STATIC_HELP": "Nie należy do żadnego zestawu. Nie wyśrodkowuje."
|
|
||||||
},
|
|
||||||
"AUTOSTART": "Uruchom automatycznie przy starcie",
|
|
||||||
"LAUNCH": "Uruchom"
|
|
||||||
},
|
|
||||||
"DISPLAY_BRIGHTNESS": "Jasność wyświetlacza",
|
|
||||||
"PROCESS_LIST": "Lista procesów",
|
"PROCESS_LIST": "Lista procesów",
|
||||||
"REFRESH": "Odśwież",
|
"REFRESH": "Odśwież",
|
||||||
"PROCESS": {
|
"REMOVE": "Usuń",
|
||||||
"STOP": "Zatrzymaj",
|
|
||||||
"FORCE_KILL": "Wymuś zakończenie"
|
|
||||||
},
|
|
||||||
"DEBUG_INFO": "Informacje debugowania",
|
|
||||||
"CREATION_DATE": "Data utworzenia",
|
|
||||||
"DOWNLOADER": "Pobieranie",
|
|
||||||
"DOWNLOAD_AGAIN": "Pobierz ponownie",
|
|
||||||
"DOWNLOADING_FILE": "Pobieranie pliku...",
|
|
||||||
"GETTING_STARTED": "Rozpoczęcie",
|
|
||||||
"MODIFICATION_DATE": "Data modyfikacji",
|
|
||||||
"LOADING": "Ładowanie...",
|
|
||||||
"APPLY": "Zastosuj",
|
"APPLY": "Zastosuj",
|
||||||
"RELOAD_FROM_DISK": "Przeładuj z dysku",
|
"RELOAD_FROM_DISK": "Przeładuj z dysku",
|
||||||
|
"SETTINGS": "Ustawienia",
|
||||||
|
"SHOW": "Pokaż",
|
||||||
"TARGET_PATH": "Ścieżka docelowa",
|
"TARGET_PATH": "Ścieżka docelowa",
|
||||||
|
"TERMINATE_PROCESS": "Zakończ proces",
|
||||||
"VERSION": "Wersja",
|
"VERSION": "Wersja",
|
||||||
"DONATE": {
|
"WIDTH": "Szerokość",
|
||||||
"SUPPORT_US": "Wesprzyj nas",
|
"PINNED_APPS": "Przypięte aplikacje",
|
||||||
"DESCRIPTION": "Jesteśmy małym, dwuosobowym zespołem programistów, którzy tworzą WayVR w wolnym czasie. Jeśli korzystanie z tego oprogramowania sprawia Ci przyjemność, rozważ wsparcie nas – każda darowizna pomaga nam działać dalej.",
|
"SAVED_TO_FAVOURITES": "Dodano do przypiętych aplikacji",
|
||||||
"BUTTON_TOOLTIP": "Przekaż darowiznę przez Open Collective",
|
"ADD_TO_FAVOURITES": "Przypnij aplikację",
|
||||||
"CURRENT_SUPPORTERS": "Obecni Wspierający",
|
"ADD_TO_FAVOURITES_HINT": "Zapisz preset i przypnij go do szuflady aplikacji",
|
||||||
"THANK_YOU_WAYVR": "Dziękujemy od zespołu WayVR!"
|
"REMOVE_FROM_FAVOURITES": "Usuń z przypiętych aplikacji",
|
||||||
},
|
"EMPTY": "Puste"
|
||||||
"WELCOME": {
|
|
||||||
"ALL_SET": "Wszystko gotowe!",
|
|
||||||
"BASICS": "Te podstawowe informacje pozwolą Ci z łatwością zacząć korzystać z WayVR.",
|
|
||||||
"CENTER_MARKER": "Znacznik środka określa środek Twojego zestawu.",
|
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "Naciśnij dwukrotnie przycisk B (na Index) lub Y (na Meta), aby przełączyć widoczność swojej przestrzeni roboczej. Spróbuj teraz.",
|
|
||||||
"FEATURES_DOCUMENTATION": "Istnieje wiele innych funkcji, które warto spersonalizować. Aby uzyskać więcej informacji, sprawdź dokumentację pod adresem:",
|
|
||||||
"FINISH_TUTORIAL": "Zakończ samouczek",
|
|
||||||
"GRAB_BOTH_HANDS": "Chwyć to obiema rękami, jeśli chcesz przenieść konkretny overlay ze swojego zestawu.",
|
|
||||||
"GRAB_ONE_HAND": "Chwyć to jedną ręką, aby przemieścić swój zestaw.",
|
|
||||||
"GREETING": "Cześć!",
|
|
||||||
"GUIDE_INTRO": "Pozwól nam przeprowadzić Cię przez Twoje pierwsze kroki.",
|
|
||||||
"LASER_COLORS": "Kolory lasera",
|
|
||||||
"LASER_FUNCTIONALITY": "Wiele funkcji w WayVR zależy od koloru lasera używanego do interakcji z elementami interfejsu użytkownika. Nie musisz naciskać tych przycisków, wystarczy je dotknąć!",
|
|
||||||
"LAST_PAGE_INFO": "Ten samouczek przestanie się pojawiać po dotarciu do ostatniej strony.",
|
|
||||||
"LOOK_AT_LEFT_WRIST": "Spójrz na swój lewy nadgarstek. To jest Twój watch.",
|
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Tryb środkowego przycisku: Fioletowy laser",
|
|
||||||
"MOVING_YOUR_SET": "Przesuwanie Twojego zestawu",
|
|
||||||
"NEXT_BUTTON": "Naciśnij poniższy przycisk „Dalej”, aby rozpocząć.",
|
|
||||||
"REGULAR_MODE_BLUE_LASER": "— Tryb regularny: Niebieski laser",
|
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Zmień położenie tego okna, używając przycisku chwytu (grip) na kontrolerze.",
|
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Tryb prawego przycisku: Pomarańczowy laser",
|
|
||||||
"THANKS_FOR_INSTALLING": "Dziękujemy za zainstalowanie WayVR!",
|
|
||||||
"WATCH": "Watch",
|
|
||||||
"WORKING_SET": "Aktywny zestaw"
|
|
||||||
},
|
|
||||||
"DOWNLOAD": "Pobierz"
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,156 +1,77 @@
|
||||||
{
|
{
|
||||||
|
"DEFINITIONS": {
|
||||||
|
"ANCHORED": "同步移动",
|
||||||
|
"FLOATING": "悬浮",
|
||||||
|
"STATIC": "静态",
|
||||||
|
"SET": "套装",
|
||||||
|
"WATCH": "手表",
|
||||||
|
"DASHBOARD": "控制面板",
|
||||||
|
"EDIT_MODE": "编辑模式",
|
||||||
|
"SETTINGS": "设置",
|
||||||
|
"KEYBOARD": "键盘",
|
||||||
|
"TASKBAR": "任务栏",
|
||||||
|
"FEATURES": "功能",
|
||||||
|
"OVERLAY": "叠加层",
|
||||||
|
"SKYMAP": "天空盒",
|
||||||
|
"PLAYSPACE": "活动空间",
|
||||||
|
"D_PAD": "方向键"
|
||||||
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"RECENTER_PLAYSPACE": "重置游玩区中心"
|
"RECENTER_PLAYSPACE": "重新中心化活动空间"
|
||||||
},
|
},
|
||||||
"APP_LAUNCHER": {
|
"APP_LAUNCHER": {
|
||||||
"ASPECT": {
|
"ASPECT": {
|
||||||
"SEMI_TALL": "略高",
|
"SEMI_TALL": "半高",
|
||||||
"SEMI_WIDE": "略宽",
|
"SEMI_WIDE": "半宽",
|
||||||
"SQUARE": "正方形",
|
"SQUARE": "正方形",
|
||||||
"TALL": "高",
|
"TALL": "纵向",
|
||||||
"WIDE": "宽"
|
"WIDE": "宽屏"
|
||||||
},
|
},
|
||||||
"ASPECT_TITLE": "比例",
|
"ASPECT_TITLE": "宽高比",
|
||||||
"AUTOSTART": "启动时自动运行",
|
"AUTOSTART": "启动时自动运行",
|
||||||
"LAUNCH": "启动",
|
"LAUNCH": "启动",
|
||||||
"MODE": {
|
"MODE": {
|
||||||
"CAGE": "兼容模式 (Cage)",
|
"CAGE": "兼容模式 (Cage)",
|
||||||
"NATIVE": "原生模式"
|
"NATIVE": "原生模式"
|
||||||
},
|
},
|
||||||
"POS": {
|
|
||||||
"ANCHORED": "锚定",
|
|
||||||
"ANCHORED_HELP": "相对于中心标记保持固定。",
|
|
||||||
"FLOATING": "悬浮",
|
|
||||||
"FLOATING_HELP": "独立移动,显示时自动重置中心。",
|
|
||||||
"STATIC": "静态",
|
|
||||||
"STATIC_HELP": "不属于任何集合。不会重置中心。"
|
|
||||||
},
|
|
||||||
"POS_TITLE": "定位",
|
|
||||||
"RES_TITLE": "分辨率"
|
"RES_TITLE": "分辨率"
|
||||||
},
|
},
|
||||||
"APP_SETTINGS": {
|
"APP_SETTINGS": {
|
||||||
"ALLOW_SLIDING": "抓取时允许摇杆交互",
|
"ALLOW_SLIDING": "抓取时允许摇杆交互",
|
||||||
"ANIMATION_SPEED": "UI 动画速度",
|
"ANIMATION_SPEED": "UI 动画速度",
|
||||||
|
"AUTOSTART_APPS": "启动时运行的应用程序",
|
||||||
"BLOCK_GAME_INPUT": "屏蔽游戏输入",
|
"BLOCK_GAME_INPUT": "屏蔽游戏输入",
|
||||||
"BLOCK_GAME_INPUT_HELP": "悬停在覆盖层上时屏蔽所有输入",
|
"BLOCK_GAME_INPUT_HELP": "当悬停在覆盖层上时,屏蔽所有输入",
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "屏蔽输入时忽略手表",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "拦截输入时忽略手表",
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "悬停在手表上时不屏蔽输入",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "当光标悬停在手表上时,不拦截输入",
|
||||||
"CAPTURE_METHOD": "Wayland 屏幕采集",
|
"BLOCK_POSES_ON_KBD_INTERACTION": "与键盘交互时禁用姿态输入",
|
||||||
"CAPTURE_METHOD_HELP": "如果您遇到黑屏或花屏,请尝试更改此项",
|
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "当光标悬停在键盘上且启用了“拦截游戏输入”时,拦截游戏接收的姿态数据",
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "清除 PipeWire 令牌",
|
|
||||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "下次启动时提示选择屏幕",
|
|
||||||
"CLEAR_SAVED_STATE": "清除保存的状态",
|
|
||||||
"CLEAR_SAVED_STATE_HELP": "重置集合与覆盖层位置",
|
|
||||||
"CLICK_FREEZE_TIME_MS": "点击冻结时间 (毫秒)",
|
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "有助于提高双击精度",
|
|
||||||
"CLOCK_12H": "12 小时制时钟",
|
|
||||||
"CONTROLS": "控制",
|
|
||||||
"DELETE_ALL_CONFIGS": "擦除配置",
|
|
||||||
"DELETE_ALL_CONFIGS_HELP": "从 conf.d 中删除所有配置文件",
|
|
||||||
"DOUBLE_CURSOR_FIX": "双光标修复",
|
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "如果您看到两个光标,请启用此项",
|
|
||||||
"FEATURES": "功能",
|
|
||||||
"FOCUS_FOLLOWS_MOUSE_MODE": "触摸扳机时移动鼠标",
|
|
||||||
"HIDE_GRAB_HELP": "隐藏抓取帮助",
|
|
||||||
"HIDE_USERNAME": "隐藏用户名",
|
|
||||||
"INVERT_SCROLL_DIRECTION_X": "反转水平滚动方向",
|
|
||||||
"INVERT_SCROLL_DIRECTION_Y": "反转垂直滚动方向",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK": "键盘中键点击",
|
|
||||||
"KEYBOARD_MIDDLE_CLICK_HELP": "使用紫色激光打字时的修饰键",
|
|
||||||
"KEYBOARD_SOUND_ENABLED": "键盘音效",
|
|
||||||
"LEFT_HANDED_MOUSE": "左手鼠标",
|
|
||||||
"LEFT_HANDED_MOUSE_HELP": "如果鼠标按钮反置,请使用此项",
|
|
||||||
"LONG_PRESS_DURATION": "长按持续时间",
|
|
||||||
"LOOK_AND_FEEL": "外观与体验",
|
|
||||||
"MISC": "杂项",
|
|
||||||
"NOTIFICATIONS_ENABLED": "启用通知",
|
|
||||||
"NOTIFICATIONS_SOUND_ENABLED": "通知音效",
|
|
||||||
"OPAQUE_BACKGROUND": "不透明背景",
|
|
||||||
"OPTION": {
|
|
||||||
"AUTO": "自动",
|
|
||||||
"AUTO_HELP": "如果支持,则使用 ScreenCopy GPU,\n否则使用 PipeWire GPU。",
|
|
||||||
"PIPEWIRE_HELP": "快速 GPU 采集,\n所有桌面环境的标准方式。",
|
|
||||||
"PW_FALLBACK_HELP": "高 CPU 占用的慢速方法。\n在 PipeWire GPU 不起作用时尝试。",
|
|
||||||
"SCREENCOPY_GPU_HELP": "快速,无屏幕共享弹窗。\n支持:Hyprland, Niri, River, Sway",
|
|
||||||
"SCREENCOPY_HELP": "慢速,无屏幕共享弹窗。\n支持:Hyprland, Niri, River, Sway",
|
|
||||||
"NONE": "无",
|
|
||||||
"HMD_PINCH": "HMD + 捏合",
|
|
||||||
"EYE_PINCH": "眼睛 + 捏合",
|
|
||||||
"EYE_ONLY": "仅眼球",
|
|
||||||
"HMD_ONLY": "仅限头显",
|
|
||||||
"NONE_INPUT_HELP": "不模拟鼠标和键盘。\n将无法与屏幕进行交互。",
|
|
||||||
"UINPUT": "设备模拟",
|
|
||||||
"UINPUT_HELP": "使用 uinput 模块来模拟设备。\n您的用户必须处于 input 用户组中。\n已知在大多数桌面上运行良好。",
|
|
||||||
"WL_VIRTUAL": "Wayland 虚拟输入",
|
|
||||||
"WL_VIRTUAL_HELP": "使用 zwlr_virtual_pointer 和 zwp_virtual_keyboard 向 Wayland 合成器发送事件。\n仅在部分桌面环境下能可靠工作。\n在 KDE、GNOME 或 COSMIC 上无法工作。"
|
|
||||||
},
|
|
||||||
"POINTER_LERP_FACTOR": "指针平滑",
|
|
||||||
"RESTART_SOFTWARE": "重启软件",
|
|
||||||
"RESTART_SOFTWARE_HELP": "应用需要重启的设置",
|
|
||||||
"ROUND_MULTIPLIER": "UI 边缘圆角",
|
|
||||||
"SCREEN_RENDER_DOWN": "以较低分辨率渲染屏幕",
|
|
||||||
"SCREEN_RENDER_DOWN_HELP": "有助于解决高分辨率屏幕的锯齿问题",
|
|
||||||
"SCROLL_SPEED": "滚动速度",
|
|
||||||
"SETS_ON_WATCH": "在手表上显示集合",
|
|
||||||
"SPACE_DRAG_MULTIPLIER": "空间拖拽倍率",
|
|
||||||
"SPACE_DRAG_UNLOCKED": "允许在所有轴上进行空间拖拽",
|
|
||||||
"SPACE_ROTATE_UNLOCKED": "允许在所有轴上进行空间旋转",
|
|
||||||
"TROUBLESHOOTING": "故障排除",
|
|
||||||
"UPRIGHT_SCREEN_FIX": "垂直屏幕修复",
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "修复某些桌面上的垂直屏幕问题",
|
|
||||||
"USE_PASSTHROUGH": "启用穿透",
|
|
||||||
"USE_PASSTHROUGH_HELP": "如果 XR 运行时支持,则允许穿透",
|
|
||||||
"USE_SKYBOX": "启用天空盒",
|
|
||||||
"USE_SKYBOX_HELP": "如果没有场景应用或穿透,则显示天空盒",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用",
|
|
||||||
"AUTOSTART_APPS": "开机启动应用",
|
|
||||||
"HANDSFREE_POINTER": "免提模式",
|
|
||||||
"HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取,右手为点击。",
|
|
||||||
"UI_GRADIENT_INTENSITY": "UI 渐变强度",
|
|
||||||
"RESET_PLAYSPACE": "重置游戏空间",
|
|
||||||
"RESET_PLAYSPACE_HELP": "清除舞台空间偏移。",
|
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION": "与键盘交互时阻止姿势",
|
|
||||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "当键盘悬停且启用“阻止游戏输入”时,阻止游戏接收姿势",
|
|
||||||
"LANGUAGE": "语言",
|
|
||||||
"REQUIRES_RESTART": "需要重启",
|
|
||||||
"GRID_OPACITY": "地面网格不透明度",
|
|
||||||
"GRID_OPACITY_HELP": "启用天空盒时地板网格的不透明度",
|
|
||||||
"BROWSE_ONLINE_CATALOG": "浏览在线目录...",
|
|
||||||
"BROWSE_SKYMAPS": "浏览 Skymaps",
|
|
||||||
"COLOR_KEYING": "颜色键控",
|
|
||||||
"NO_SKYMAPS_FOUND": "未找到 Skymaps",
|
|
||||||
"SELECT_VARIANT": "选择变体",
|
|
||||||
"SHOW_WELCOME_SCREEN": "显示欢迎屏幕",
|
|
||||||
"SKYBOX": "Skybox",
|
|
||||||
"SKYMAP_ALREADY_DOWNLOADED": "此 Skymap 已下载。请选择所需操作。",
|
|
||||||
"WATCH_VIEW_ANGLE": "Watch 视角角度",
|
|
||||||
"WATCH_VIEW_ANGLE_HELP": "控制表盘的淡出方式",
|
|
||||||
"BINDINGS": {
|
"BINDINGS": {
|
||||||
"COMP": {
|
"COMP": {
|
||||||
"CLICK": "点击",
|
"CLICK": "点击",
|
||||||
"FORCE": "力度",
|
"FORCE": "力度",
|
||||||
"TOUCH": "触摸",
|
"TOUCH": "触碰",
|
||||||
"VALUE": "值",
|
"VALUE": "数值",
|
||||||
"PROXIMITY": "临近度",
|
"PROXIMITY": "距离",
|
||||||
"X_AXIS": "X 轴",
|
"X_AXIS": "X 轴",
|
||||||
"Y_AXIS": "Y 轴"
|
"Y_AXIS": "Y 轴"
|
||||||
},
|
},
|
||||||
"TYPE": {
|
"TYPE": {
|
||||||
"BUMPER": "侧键",
|
"BUMPER": "肩键",
|
||||||
"DPAD_UP": "方向键上",
|
"DPAD_UP": "方向键-上",
|
||||||
"DPAD_DOWN": "方向键下",
|
"DPAD_DOWN": "方向键-下",
|
||||||
"DPAD_LEFT": "方向键左",
|
"DPAD_LEFT": "方向键-左",
|
||||||
"DPAD_RIGHT": "方向键右",
|
"DPAD_RIGHT": "方向键-右",
|
||||||
"JOYSTICK": "摇杆",
|
"JOYSTICK": "摇杆",
|
||||||
"MENU": "菜单",
|
"MENU": "菜单",
|
||||||
"SHOULDER": "肩键",
|
"SHOULDER": "肩键",
|
||||||
"SQUEEZE": "抓取",
|
"SQUEEZE": "握持",
|
||||||
"SYSTEM": "系统",
|
"SYSTEM": "系统",
|
||||||
"THUMBREST": "拇指托",
|
"THUMBREST": "大拇指托",
|
||||||
"THUMBSTICK": "摇杆",
|
"THUMBSTICK": "摇杆 (Thumbstick)",
|
||||||
"TRACKPAD": "触控板",
|
"TRACKPAD": "触控板",
|
||||||
"TRIGGER": "扳机键",
|
"TRIGGER": "扳机键",
|
||||||
"VIEW": "视图"
|
"VIEW": "View 键"
|
||||||
},
|
},
|
||||||
"CLICK": {
|
"CLICK": {
|
||||||
"ANY": "任意",
|
"ANY": "任意",
|
||||||
|
|
@ -162,60 +83,179 @@
|
||||||
"CLICK": "点击*",
|
"CLICK": "点击*",
|
||||||
"GRAB": "抓取*",
|
"GRAB": "抓取*",
|
||||||
"ALT_CLICK": "自定义 Shell 执行 (在配置中设置 alt_click)",
|
"ALT_CLICK": "自定义 Shell 执行 (在配置中设置 alt_click)",
|
||||||
"SHOW_HIDE": "显示、隐藏、重新中心化*",
|
"SHOW_HIDE": "显示、隐藏、居中*",
|
||||||
"TOGGLE_DASHBOARD": "切换控制面板",
|
"TOGGLE_DASHBOARD": "切换控制面板",
|
||||||
"SPACE_DRAG": "Playspace 拖拽",
|
"SPACE_DRAG": "活动空间拖拽",
|
||||||
"SPACE_ROTATE": "Playspace 旋转",
|
"SPACE_ROTATE": "旋转活动空间",
|
||||||
"SPACE_RESET": "Playspace 重置",
|
"SPACE_RESET": "重置活动空间",
|
||||||
"CLICK_MODIFIER_RIGHT": "右键修饰键",
|
"CLICK_MODIFIER_RIGHT": "右键修饰键",
|
||||||
"CLICK_MODIFIER_MIDDLE": "中键修饰键",
|
"CLICK_MODIFIER_MIDDLE": "中键点击修饰键",
|
||||||
"MOVE_MOUSE": "移动鼠标 (如果默认关闭)",
|
"MOVE_MOUSE": "移动鼠标(默认关闭)",
|
||||||
"SCROLL": "滚动*"
|
"SCROLL": "滚动*"
|
||||||
},
|
},
|
||||||
"LEFT": "左侧",
|
"LEFT": "左手",
|
||||||
"RIGHT": "右",
|
"RIGHT": "右侧",
|
||||||
"COMPONENT": "触发类型",
|
"COMPONENT": "触发类型",
|
||||||
"SUBPATH": "动作控制",
|
"SUBPATH": "激活控件",
|
||||||
"THRESHOLD": "高于上限值时激活\n低于下限值时停用"
|
"THRESHOLD": "高于上限值时激活\n低于下限值时取消激活"
|
||||||
},
|
},
|
||||||
|
"BROWSE_ONLINE_CATALOG": "浏览在线目录...",
|
||||||
|
"BROWSE_SKYMAPS": "浏览天空盒",
|
||||||
|
"CAPTURE_METHOD": "屏幕采集方式",
|
||||||
|
"CAPTURE_METHOD_HELP": "如果屏幕出现黑色或花屏,请尝试更改此项",
|
||||||
|
"COLOR_KEYING": "颜色键控",
|
||||||
|
"COLOR_PALETTE": "颜色面板",
|
||||||
|
"COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义方案,请访问网站!",
|
||||||
|
"COLOR_PALETTES": "配色方案",
|
||||||
|
"COLOR_PALETTE_CURRENT": "当前激活的主题。",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "添加自定义主题!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "点击查看网络手册",
|
||||||
|
"COLOR_PALETTE_ACTIVATE": "点击使用此主题。",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS": "清除 PipeWire 令牌",
|
||||||
|
"CLEAR_PIPEWIRE_TOKENS_HELP": "下次启动时提示选择屏幕",
|
||||||
|
"CLEAR_SAVED_STATE": "清除保存的状态",
|
||||||
|
"CLEAR_SAVED_STATE_HELP": "重置套装与叠加层位置",
|
||||||
|
"CLICK_FREEZE_TIME_MS": "点击冻结时间 (ms)",
|
||||||
|
"CLICK_FREEZE_TIME_MS_HELP": "提高双击精度",
|
||||||
|
"CLOCK_12H": "12 小时制",
|
||||||
|
"CONTROLS": "控制",
|
||||||
|
"DELETE_ALL_CONFIGS": "重置配置",
|
||||||
|
"DELETE_ALL_CONFIGS_HELP": "删除 conf.d 中的所有配置文件",
|
||||||
|
"DOUBLE_CURSOR_FIX": "双光标修复",
|
||||||
|
"DOUBLE_CURSOR_FIX_HELP": "看到两个光标时请开启此项",
|
||||||
|
"DEFAULT_OVERLAY_SCALE": "默认叠加层大小",
|
||||||
|
"DEFAULT_OVERLAY_SCALE_HELP": "新生成的叠加层将以此比例显示。",
|
||||||
|
"DEFAULT_CURVATURE": "默认叠加层曲率",
|
||||||
|
"DEFAULT_OPACITY": "默认叠加层不透明度",
|
||||||
|
"DEFAULT_POSITIONING": "叠加层默认位置",
|
||||||
|
"OVERLAY_DEFAULTS_HELP": "仅适用于新创建的叠加层",
|
||||||
"ENABLED": "已启用",
|
"ENABLED": "已启用",
|
||||||
"INPUT_EMULATION_METHOD": "输入仿真方法",
|
"FEATURES": "功能",
|
||||||
"INPUT_EMULATION_METHOD_HELP": "如果鼠标或键盘输入未被识别,请尝试更改此设置。",
|
"FOCUS_FOLLOWS_MOUSE_MODE": "触摸扳机移动鼠标",
|
||||||
"INPUT_PROFILES": "更改输入绑定",
|
"HANDSFREE_POINTER": "免手持模式",
|
||||||
|
"HANDSFREE_POINTER_HELP": "无手柄时的输入方式。\n左手捏合为抓取,右手捏合为点击。",
|
||||||
|
"HANDSFREE_ALT_TAB": "应用切换器瞄准方式",
|
||||||
|
"HANDSFREE_ALT_TAB_HELP": "按住 Super+X,对准目标窗口,然后松开以切换焦点。",
|
||||||
|
"HIDE_GRAB_HELP": "隐藏抓取提示",
|
||||||
|
"HIDE_USERNAME": "隐藏用户名",
|
||||||
|
"INPUT_EMULATION_METHOD": "输入模拟方式",
|
||||||
|
"INPUT_EMULATION_METHOD_HELP": "如果鼠标或键盘输入没有反应,请尝试更改此项。",
|
||||||
|
"INPUT_CAPTURE_METHOD": "输入捕获方式",
|
||||||
|
"INPUT_CAPTURE_METHOD_HELP": "允许在 WayVR 中使用物理外设。\n Super+Z:在 WayVR 和真实桌面之间切换输入\n Super+X:在 WayVR 应用之间切换",
|
||||||
|
"INPUT_PROFILES": "修改输入绑定",
|
||||||
"INPUT_PROFILES_HELP": "OpenXR 控制器输入绑定",
|
"INPUT_PROFILES_HELP": "OpenXR 控制器输入绑定",
|
||||||
"NOT_SUPPORTED": "不支持",
|
"INVERT_SCROLL_DIRECTION_X": "反转水平滚动方向",
|
||||||
|
"INVERT_SCROLL_DIRECTION_Y": "反转垂直滚动方向",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK": "键盘鼠标中键",
|
||||||
|
"KEYBOARD_MIDDLE_CLICK_HELP": "使用紫色激光输入时的\n修饰键",
|
||||||
|
"KEYBOARD_SOUND_ENABLED": "键盘声音",
|
||||||
|
"LANGUAGE": "语言",
|
||||||
|
"LEFT_HANDED_MOUSE": "左手鼠标模式",
|
||||||
|
"LEFT_HANDED_MOUSE_HELP": "若鼠标按键已互换,请启用此项",
|
||||||
|
"LONG_PRESS_DURATION": "长按时间",
|
||||||
|
"LOOK_AND_FEEL": "外观与体感",
|
||||||
|
"MISC": "其他",
|
||||||
|
"NOTIFICATIONS_ENABLED": "开启通知",
|
||||||
|
"NOTIFICATIONS_SOUND_ENABLED": "通知音效",
|
||||||
|
"NOT_SUPPORTED": "暂不支持",
|
||||||
|
"NO_SKYMAPS_FOUND": "未找到天空盒",
|
||||||
|
"OPAQUE_BACKGROUND": "不透明背景",
|
||||||
|
"OPTION": {
|
||||||
|
"ANCHORED_HELP": "随中心标记移动。推荐。",
|
||||||
|
"FLOATING_HELP": "独立移动,自动居中。\n容易丢失位置;不推荐使用。",
|
||||||
|
"STATIC_HELP": "相对于世界空间保持固定。",
|
||||||
|
"AUTO": "自动",
|
||||||
|
"AUTO_HELP": "优先使用 ScreenCopy GPU,\n否则使用 PipeWire GPU。",
|
||||||
|
"EYE_ONLY": "眼动激光",
|
||||||
|
"EYE_PINCH": "注视 + 捏合",
|
||||||
|
"HMD_ONLY": "HMD 激光指针",
|
||||||
|
"HMD_PINCH": "头显 + 捏合",
|
||||||
|
"NONE": "无",
|
||||||
|
"NONE_INPUT_HELP": "不模拟鼠标和键盘。\n无法与屏幕进行交互。",
|
||||||
|
"NONE_INPUT_CAPTURE_HELP": "不捕获鼠标和键盘。\n在 WayVR 中启动的应用将无法使用\n实体鼠标或键盘。",
|
||||||
|
"PIPEWIRE_HELP": "快速 GPU 采集,\n所有桌面端的标准配置。",
|
||||||
|
"PW_FALLBACK_HELP": "较慢且 CPU 占用较高。\n在 PipeWire GPU 模式无效时尝试使用。",
|
||||||
|
"SCREENCOPY_GPU_HELP": "速度快,且没有屏幕共享弹窗。\n适用于:Hyprland, Niri, River, Sway",
|
||||||
|
"SCREENCOPY_HELP": "速度较慢,无屏幕共享弹窗。\n适用:Hyprland, Niri, River, Sway",
|
||||||
|
"UINPUT": "设备模拟",
|
||||||
|
"UINPUT_HELP": "使用 uinput 模块来模拟设备。\n在大多数桌面环境下运行良好。",
|
||||||
|
"EVDEV_HELP": "独占捕捉输入设备。\n用户必须在 input 组中。",
|
||||||
|
"WL_VIRTUAL": "Wayland 虚拟输入",
|
||||||
|
"WL_VIRTUAL_HELP": "使用 zwlr_virtual_pointer 和 zwp_virtual_keyboard 向 Wayland 合成器发送事件。\n仅在部分桌面环境下运行稳定。\n在 KDE、GNOME 或 COSMIC 上无效。"
|
||||||
|
},
|
||||||
|
"POINTER_ACCELERATION": "鼠标加速",
|
||||||
|
"POINTER_ACCELERATION_HELP": "开启:自适应鼠标加速\n关闭:恒定速度",
|
||||||
|
"POINTER_LERP_FACTOR": "光标平滑度",
|
||||||
|
"POINTER_SPEED": "鼠标速度",
|
||||||
|
"REQUIRES_RESTART": "需要重启",
|
||||||
|
"RESET_PLAYSPACE": "重置活动空间",
|
||||||
|
"RESET_PLAYSPACE_HELP": "清除活动空间的偏移量。",
|
||||||
|
"SAVE_PLAYSPACE_CENTER": "保存活动空间中心",
|
||||||
|
"SAVE_PLAYSPACE_CENTER_HELP": "将当前的活动空间设置为重置活动空间的绑定点。",
|
||||||
|
"RESET_PLAYSPACE_CENTER": "重置活动空间中心",
|
||||||
|
"RESET_PLAYSPACE_CENTER_HELP": "重置之前设置的活动空间中心。",
|
||||||
|
"RESTART_SOFTWARE": "重启软件",
|
||||||
|
"RESTART_SOFTWARE_HELP": "应用需要重启才能生效的设置",
|
||||||
|
"ROUND_MULTIPLIER": "UI 边缘圆角",
|
||||||
|
"SCREEN_RENDER_DOWN": "低分辨率渲染屏幕",
|
||||||
|
"SCREEN_RENDER_DOWN_HELP": "有助于减轻高分辨率屏幕上的锯齿现象",
|
||||||
|
"SCROLL_SPEED": "滚动速度",
|
||||||
|
"SELECT_VARIANT": "选择变体",
|
||||||
|
"SNAP_ANGLE_DEG": "窗口俯仰与翻滚吸附角度",
|
||||||
|
"SNAP_ANGLE_DEG_HELP": "抓取窗口在俯仰轴和翻滚轴上按此角度对齐。",
|
||||||
"ENABLE_WATCH": "启用手表",
|
"ENABLE_WATCH": "启用手表",
|
||||||
"SPACE_DRAG": "空间拖拽",
|
"SETS_ON_WATCH": "手表显示套装",
|
||||||
|
"SHOW_WELCOME_SCREEN": "显示欢迎界面",
|
||||||
|
"SKYBOX": "天空图",
|
||||||
|
"SKYMAP_ALREADY_DOWNLOADED": "此天空盒已下载。请选择操作。",
|
||||||
|
"SPACE_DRAG": "活动空间",
|
||||||
|
"SPACE_DRAG_MULTIPLIER": "活动空间拖拽倍率",
|
||||||
|
"SPACE_DRAG_AFFECTS_WORLD": "移动活动空间时保留叠加层位置",
|
||||||
|
"SPACE_DRAG_UNLOCKED": "允许在所有轴向上进行空间拖拽",
|
||||||
"SPACE_GRAVITY_DAMPING": "阻尼",
|
"SPACE_GRAVITY_DAMPING": "阻尼",
|
||||||
"SPACE_GRAVITY_DAMPING_HELP": "用于减缓移动速度的人造阻力。0.1 - 高阻力,1.0 - 无阻力",
|
"SPACE_GRAVITY_DAMPING_HELP": "用于减缓运动的人造阻尼。0.1 - 高阻尼,1.0 - 无阻尼",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH": "投掷力度",
|
"SPACE_GRAVITY_FLING_STRENGTH": "弹射强度",
|
||||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Space-drag 后的重力发射力强度倍数。\n0.0 - 完全没有位移,2.0 - 双倍强度",
|
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "活动空间拖拽后重力发射强度的倍数。\n0.0 - 完全不动,2.0 - 强度加倍",
|
||||||
"SPACE_GRAVITY_GRAVITY": "重力",
|
"SPACE_GRAVITY_GRAVITY": "重力",
|
||||||
"SPACE_GRAVITY_GRAVITY_HELP": "向下作用的力的大小。0.0 - 无重力",
|
"SPACE_GRAVITY_GRAVITY_HELP": "向下的力大小。0.0 - 无重力",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION": "地面摩擦力",
|
"SPACE_GRAVITY_GROUND_FRICTION": "地面摩擦力",
|
||||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "如果你接触地面时,减慢你移动速度的摩擦力大小。\n0.0 - 无摩擦(就像在冰面上一样),1.0 - 粗糙表面",
|
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "触地时的摩擦力大小。\n0.0 - 无摩擦(像在冰上一样),1.0 - 粗糙表面",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "地面高度",
|
"SPACE_GRAVITY_FLOOR_HEIGHT": "地板高度",
|
||||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "地面所在 Y 轴位置。达到该高度时重力停止。",
|
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "地板所在的 Y 轴位置。到达此高度时重力停止作用。",
|
||||||
"SAVE": "保存",
|
"SPACE_ROTATE_UNLOCKED": "允许活动空间在所有轴上旋转",
|
||||||
"CANCEL": "取消",
|
"TROUBLESHOOTING": "故障排除",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UI 渐变强度",
|
||||||
|
"UPRIGHT_SCREEN_FIX": "垂直屏幕修复",
|
||||||
|
"UPRIGHT_SCREEN_FIX_HELP": "修复部分桌面端屏幕方向不正确的问题",
|
||||||
|
"USE_PASSTHROUGH": "启用透视模式",
|
||||||
|
"USE_PASSTHROUGH_HELP": "若 XR 运行时支持,则允许透视模式",
|
||||||
|
"USE_SKYBOX": "显示天空盒",
|
||||||
|
"USE_SKYBOX_HELP": "如果没有场景应用或透视模式,则显示天空盒",
|
||||||
|
"WATCH_VIEW_ANGLE": "手表视角范围",
|
||||||
|
"WATCH_VIEW_ANGLE_HELP": "控制手表的渐隐效果",
|
||||||
"WHISPER": {
|
"WHISPER": {
|
||||||
"NEED_TO_DOWNLOAD_MODEL": "所选模型需要下载。\n现在开始下载吗?",
|
"NEED_TO_DOWNLOAD_MODEL": "选中的模型需要下载。\n现在下载吗?",
|
||||||
"REMOVE_UNUSED_MODELS": "您正在关闭语音转文本功能。\n是否删除已下载的 Whisper 模型以释放空间?"
|
"REMOVE_UNUSED_MODELS": "正在关闭语音转文本功能。\n是否删除已下载的 Whisper 模型以释放空间?"
|
||||||
},
|
},
|
||||||
"WHISPER_MODEL": "语音转文本模型",
|
"WHISPER_MODEL": "语音转文本模型",
|
||||||
"WHISPER_MODEL_HELP": "要使用的 Whisper 模型。\n模型越大,结果越准确,\n但消耗的显存 (VRAM) 越多。"
|
"WHISPER_MODEL_HELP": "所使用的 Whisper 模型。\n模型越大,结果越准确,\n但占用的显存 (VRAM) 越多。",
|
||||||
|
"GRID_OPACITY": "地面网格不透明度",
|
||||||
|
"GRID_OPACITY_HELP": "启用天空盒时地面网格的不透明度",
|
||||||
|
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用程序",
|
||||||
|
"SAVE": "保存",
|
||||||
|
"CANCEL": "取消"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "应用启动器",
|
"APPLICATION_LAUNCHER": "应用启动器",
|
||||||
"APPLICATION_STARTED": "应用已启动",
|
"APPLICATION_STARTED": "应用程序已启动",
|
||||||
"APPLICATIONS": "应用",
|
"APPLICATIONS": "应用程序",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
"AUTO_SWITCH_TO_VR_AUDIO": "自动切换到 VR 音频",
|
"AUTO_SWITCH_TO_VR_AUDIO": "自动切换至 VR 音频",
|
||||||
"CARDS": "声卡",
|
"CARDS": "声卡",
|
||||||
"FAILED_TO_SWITCH_MICROPHONE": "切换麦克风失败",
|
"FAILED_TO_SWITCH_MICROPHONE": "麦克风切换失败",
|
||||||
"MICROPHONE_SET_SUCCESSFULLY": "麦克风设置成功",
|
"MICROPHONE_SET_SUCCESSFULLY": "麦克风设置成功",
|
||||||
"MICROPHONES": "麦克风",
|
"MICROPHONES": "麦克风",
|
||||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "未找到 VR 麦克风。请手动切换。",
|
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "未找到 VR 麦克风,请手动切换。",
|
||||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "未找到 VR 扬声器。请手动切换。",
|
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "未检测到 VR 扬声器,请手动切换。",
|
||||||
"SELECT_AUDIO_CARD_PROFILE": "选择声卡配置",
|
"SELECT_AUDIO_CARD_PROFILE": "选择声卡配置",
|
||||||
"SETTINGS": "音频设置",
|
"SETTINGS": "音频设置",
|
||||||
"SPEAKERS": "扬声器",
|
"SPEAKERS": "扬声器",
|
||||||
|
|
@ -223,78 +263,87 @@
|
||||||
"VOLUME": "音量"
|
"VOLUME": "音量"
|
||||||
},
|
},
|
||||||
"CLOSE_WINDOW": "关闭窗口",
|
"CLOSE_WINDOW": "关闭窗口",
|
||||||
"DISPLAY_BRIGHTNESS": "显示亮度",
|
"CREATION_DATE": "创建日期",
|
||||||
"FAILED_TO_LAUNCH_APPLICATION": "启动应用失败:",
|
"DEBUG_INFO": "调试信息",
|
||||||
|
"DISPLAY_BRIGHTNESS": "屏幕亮度",
|
||||||
|
"DONATE": {
|
||||||
|
"SUPPORT_US": "支持我们",
|
||||||
|
"DESCRIPTION": "我们是由两名开发者组成的小团队,在业余时间构建 WayVR。如果你喜欢这款软件,请考虑支持我们 —— 每一份捐赠都能帮助我们坚持下去。",
|
||||||
|
"THANK_YOU_WAYVR": "WayVR 团队向您致谢!",
|
||||||
|
"BUTTON_TOOLTIP": "通过 Open Collective 捐赠",
|
||||||
|
"CURRENT_SUPPORTERS": "当前支持者",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "由 {USER} 赞助|感谢 {USER} 的支持|由 {USER} 助力|来自 {USER} 的贡献|{USER} 让这一切成为可能|由 {USER} 维持运行|特别感谢 {USER}|{USER} 给予了支持|由 {USER} 驱动",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_RARE": "感谢 {USER} 的温暖支持|{USER} 为我们注入了能量|由 {USER} 助力成长|感谢 {USER} 的无私奉献|{USER} 让今天变得更美好|今日的动力源泉:{USER}|由 {USER} 悉心支持|感恩 {USER} 的陪伴|{USER} 是今天的闪光点",
|
||||||
|
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "今日之神:{USER}|全场 MVP:{USER}|{USER} 拯救了世界|给 {USER} 递上一朵小红花|由 {USER} 承包了今天的快乐|{USER} 承包了今日的电费|代码之光:{USER}|{USER} 拯救了我们的发际线|简直是超级英雄:{USER}|{USER} 让生产环境稳如老狗|唯一且无可替代的:{USER}|{USER} 是今天的顶梁柱"
|
||||||
|
},
|
||||||
|
"DOWNLOAD": "下载",
|
||||||
|
"DOWNLOADER": "下载管理器",
|
||||||
|
"WELCOME": {
|
||||||
|
"ALL_SET": "一切就绪!",
|
||||||
|
"BASICS": "掌握这些基础知识,即可轻松开始使用 WayVR。",
|
||||||
|
"CENTER_MARKER": "中心标记在重新对齐时会出现在你面前。请围绕它布置叠加层!",
|
||||||
|
"DOUBLE_PRESS_TO_TOGGLE": "双击 B 键(Index)或 Y 键(Meta)以显示、重置中心或隐藏您的套装。现在试一下吧。",
|
||||||
|
"FEATURES_DOCUMENTATION": "还有许多其他值得自定义的功能。欲了解更多信息,请参阅文档:",
|
||||||
|
"FINISH_TUTORIAL": "完成教程",
|
||||||
|
"GRAB_BOTH_HANDS": "如需移动 Set 中的特定覆盖层,请用双手抓取。",
|
||||||
|
"GRAB_ONE_HAND": "单手抓取以移动你的 Set。",
|
||||||
|
"GREETING": "你好!",
|
||||||
|
"GUIDE_INTRO": "让我们带你快速上手。",
|
||||||
|
"LASER_COLORS": "射线颜色",
|
||||||
|
"LASER_FUNCTIONALITY": "WayVR 的大部分功能取决于与 UI 元素交互时使用的激光颜色。无需按下这些按钮,只需触碰它们即可!",
|
||||||
|
"LAST_PAGE_INFO": "到达最后一页后,本教程将不再显示。",
|
||||||
|
"LOOK_AT_LEFT_WRIST": "看向你的左腕。那就是你的手表。",
|
||||||
|
"MIDDLE_CLICK_MODE_PURPLE_LASER": "中键模式:紫色激光",
|
||||||
|
"MOVING_YOUR_SET": "移动您的 Set",
|
||||||
|
"NEXT_BUTTON": "点击下方“下一步”按钮开始。",
|
||||||
|
"REGULAR_MODE_BLUE_LASER": "普通模式:蓝色激光",
|
||||||
|
"REPOSITION_THIS_WINDOW_BY_GRABBING": "使用控制器的抓取操作来重新定位此窗口。",
|
||||||
|
"RIGHT_CLICK_MODE_ORANGE_LASER": "右键模式:橙色激光",
|
||||||
|
"THANKS_FOR_INSTALLING": "感谢安装 WayVR!",
|
||||||
|
"WATCH": "手表",
|
||||||
|
"WORKING_SET": "当前套装"
|
||||||
|
},
|
||||||
|
"DOWNLOAD_AGAIN": "重新下载",
|
||||||
|
"DOWNLOADING_FILE": "正在下载文件...",
|
||||||
|
"FAILED_TO_LAUNCH_APPLICATION": "启动应用程序失败:",
|
||||||
"GAME_LAUNCHED": "游戏已启动",
|
"GAME_LAUNCHED": "游戏已启动",
|
||||||
"GAME_LIST": {
|
"GAME_LIST": {
|
||||||
"NO_GAMES_FOUND": "未找到游戏",
|
"NO_GAMES_FOUND": "未找到游戏",
|
||||||
"RUNNING_GAMES_LIST": "正在运行的游戏列表"
|
"RUNNING_GAMES_LIST": "运行中的游戏列表"
|
||||||
},
|
},
|
||||||
"GAMES": "游戏",
|
"GAMES": "游戏",
|
||||||
"GENERAL_SETTINGS": "通用设置",
|
"GENERAL_SETTINGS": "常规设置",
|
||||||
|
"GETTING_STARTED": "快速入门",
|
||||||
"HEIGHT": "高度",
|
"HEIGHT": "高度",
|
||||||
"HELLO": "你好!",
|
"HELLO": "你好!",
|
||||||
"HELLO_USER": "你好,{USER}!",
|
"HELLO_USER": "你好,{USER}!",
|
||||||
"HIDE": "隐藏",
|
"HIDE": "隐藏",
|
||||||
"HOME_SCREEN": "主页",
|
"HOME_SCREEN": "首页",
|
||||||
|
"MODIFICATION_DATE": "修改日期",
|
||||||
"MONADO_RUNTIME": "Monado 运行时",
|
"MONADO_RUNTIME": "Monado 运行时",
|
||||||
|
"LOADING": "加载中...",
|
||||||
"POPUP_ADD_DISPLAY": {
|
"POPUP_ADD_DISPLAY": {
|
||||||
"RESOLUTION": "分辨率"
|
"RESOLUTION": "分辨率"
|
||||||
},
|
},
|
||||||
"REMOVE": "移除",
|
"PROCESS": {
|
||||||
"SETTINGS": "设置",
|
"FORCE_KILL": "强制结束",
|
||||||
"SHOW": "显示",
|
"STOP": "停止"
|
||||||
"TERMINATE_PROCESS": "终止进程",
|
},
|
||||||
"WIDTH": "宽度",
|
|
||||||
"PROCESS_LIST": "进程列表",
|
"PROCESS_LIST": "进程列表",
|
||||||
"REFRESH": "刷新",
|
"REFRESH": "刷新",
|
||||||
"PROCESS": {
|
"REMOVE": "移除",
|
||||||
"STOP": "停止",
|
|
||||||
"FORCE_KILL": "强制关闭"
|
|
||||||
},
|
|
||||||
"DEBUG_INFO": "调试信息",
|
|
||||||
"CREATION_DATE": "创建日期",
|
|
||||||
"DOWNLOADER": "下载器",
|
|
||||||
"DOWNLOAD_AGAIN": "重新下载",
|
|
||||||
"DOWNLOADING_FILE": "正在下载文件...",
|
|
||||||
"GETTING_STARTED": "入门指南",
|
|
||||||
"MODIFICATION_DATE": "修改日期",
|
|
||||||
"LOADING": "正在加载...",
|
|
||||||
"APPLY": "应用",
|
"APPLY": "应用",
|
||||||
"RELOAD_FROM_DISK": "从磁盘重新加载",
|
"RELOAD_FROM_DISK": "从磁盘重新加载",
|
||||||
|
"SETTINGS": "设置",
|
||||||
|
"SHOW": "显示",
|
||||||
"TARGET_PATH": "目标路径",
|
"TARGET_PATH": "目标路径",
|
||||||
|
"TERMINATE_PROCESS": "终止进程",
|
||||||
"VERSION": "版本",
|
"VERSION": "版本",
|
||||||
"DONATE": {
|
"WIDTH": "宽度",
|
||||||
"SUPPORT_US": "支持我们",
|
"PINNED_APPS": "固定应用",
|
||||||
"DESCRIPTION": "我们是一个由 2 名开发者组成的精简团队,在业余时间开发 WayVR。如果您喜欢这款软件,请考虑支持我们 —— 每一次捐赠都能帮助我们继续开发下去。",
|
"SAVED_TO_FAVOURITES": "已添加到固定应用",
|
||||||
"BUTTON_TOOLTIP": "通过 Open Collective 捐赠",
|
"ADD_TO_FAVOURITES": "添加到固定应用",
|
||||||
"CURRENT_SUPPORTERS": "当前支持者",
|
"ADD_TO_FAVOURITES_HINT": "保存预设并将其固定到应用抽屉",
|
||||||
"THANK_YOU_WAYVR": "WayVR 团队向您表示感谢!"
|
"REMOVE_FROM_FAVOURITES": "从固定应用中移除",
|
||||||
},
|
"EMPTY": "暂无"
|
||||||
"WELCOME": {
|
|
||||||
"ALL_SET": "你已准备就绪!",
|
|
||||||
"BASICS": "这些基础知识将帮助您轻松开始使用 WayVR。",
|
|
||||||
"CENTER_MARKER": "中心标记确定了您 Set 的中心位置。",
|
|
||||||
"DOUBLE_PRESS_TO_TOGGLE": "双击 B(Index 控制器)或 Y(Meta 控制器)来切换工作区显示。立即尝试一下。",
|
|
||||||
"FEATURES_DOCUMENTATION": "还有许多其他值得自定义的功能。欲了解更多信息,请查看文档:",
|
|
||||||
"FINISH_TUTORIAL": "完成教程",
|
|
||||||
"GRAB_BOTH_HANDS": "如果你想移动 Set 中的特定叠加层,请用双手抓取。",
|
|
||||||
"GRAB_ONE_HAND": "用一只手抓取即可移动你的 Set。",
|
|
||||||
"GREETING": "你好!",
|
|
||||||
"GUIDE_INTRO": "让我们引导你完成初步设置。",
|
|
||||||
"LASER_COLORS": "激光颜色",
|
|
||||||
"LASER_FUNCTIONALITY": "WayVR 中的许多功能都取决于使用何种颜色的激光来与 UI 元素进行交互。您不需要按下这些按钮,只需触摸它们即可!",
|
|
||||||
"LAST_PAGE_INFO": "一旦你到达最后一页,此教程将不再显示。",
|
|
||||||
"LOOK_AT_LEFT_WRIST": "看向你的左手腕。那就是你的手表。",
|
|
||||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— 中键模式:紫色激光",
|
|
||||||
"MOVING_YOUR_SET": "正在移动您的 Set",
|
|
||||||
"NEXT_BUTTON": "按下下方的“下一步”按钮以开始。",
|
|
||||||
"REGULAR_MODE_BLUE_LASER": "— 普通模式:蓝色激光",
|
|
||||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "使用控制器的抓取操作重新定位此窗口。",
|
|
||||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "— 右键模式:橙色激光",
|
|
||||||
"THANKS_FOR_INSTALLING": "感谢安装 WayVR!",
|
|
||||||
"WATCH": "Watch",
|
|
||||||
"WORKING_SET": "工作集"
|
|
||||||
},
|
|
||||||
"DOWNLOAD": "下载"
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -2,10 +2,11 @@ use std::{path::PathBuf, rc::Rc};
|
||||||
|
|
||||||
use chrono::Timelike;
|
use chrono::Timelike;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
|
use strum::EnumCount;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::{AssetPath, AssetProvider},
|
assets::{AssetPath, AssetProvider},
|
||||||
components::button::ComponentButton,
|
components::button::ComponentButton,
|
||||||
event::StyleSetRequest,
|
event::{CallbackDataCommon, StyleSetRequest},
|
||||||
font_config::WguiFontConfig,
|
font_config::WguiFontConfig,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
|
|
@ -21,8 +22,9 @@ use wgui::{
|
||||||
use wlx_common::{
|
use wlx_common::{
|
||||||
async_executor::AsyncExecutor,
|
async_executor::AsyncExecutor,
|
||||||
audio,
|
audio,
|
||||||
dash_interface::{BoxDashInterface, ConfigChangeKind, RecenterMode},
|
dash_interface::{BoxDashInterface, ConfigChangeKind, DashPlayspaceTask},
|
||||||
locale::WayVRLangProvider,
|
locale::WayVRLangProvider,
|
||||||
|
palette::load_palette,
|
||||||
timestep::{self, Timestep},
|
timestep::{self, Timestep},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -54,13 +56,14 @@ pub struct Frontend<T> {
|
||||||
|
|
||||||
pub interface: BoxDashInterface<T>,
|
pub interface: BoxDashInterface<T>,
|
||||||
|
|
||||||
// async runtime executor
|
// single-threaded async runtime executor
|
||||||
pub executor: AsyncExecutor,
|
pub executor: AsyncExecutor,
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
state: ParserState,
|
state: ParserState,
|
||||||
|
|
||||||
current_tab: Option<Box<dyn Tab<T>>>,
|
current_tab: Option<Box<dyn Tab<T>>>,
|
||||||
|
side_buttons: Vec<(TabType, Rc<ComponentButton>)>,
|
||||||
|
|
||||||
pub tasks: FrontendTasks,
|
pub tasks: FrontendTasks,
|
||||||
|
|
||||||
|
|
@ -94,12 +97,15 @@ pub struct InitParams<'a, T> {
|
||||||
pub show_welcome: bool,
|
pub show_welcome: bool,
|
||||||
pub has_monado: bool,
|
pub has_monado: bool,
|
||||||
pub theme: Rc<WguiTheme>,
|
pub theme: Rc<WguiTheme>,
|
||||||
|
pub color_palette: &'a str,
|
||||||
|
pub executor: AsyncExecutor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum SoundType {
|
pub enum SoundType {
|
||||||
Startup,
|
Startup,
|
||||||
Launch,
|
Launch,
|
||||||
|
Save,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -127,6 +133,8 @@ impl<T: 'static> Frontend<T> {
|
||||||
let font_binary_regular = assets.load_from_path_gzip("Quicksand-Regular.ttf.gz")?;
|
let font_binary_regular = assets.load_from_path_gzip("Quicksand-Regular.ttf.gz")?;
|
||||||
let font_binary_light = assets.load_from_path_gzip("Quicksand-Light.ttf.gz")?;
|
let font_binary_light = assets.load_from_path_gzip("Quicksand-Light.ttf.gz")?;
|
||||||
|
|
||||||
|
let palette = load_palette(params.color_palette);
|
||||||
|
|
||||||
let globals = WguiGlobals::new(
|
let globals = WguiGlobals::new(
|
||||||
assets,
|
assets,
|
||||||
params.lang_provider,
|
params.lang_provider,
|
||||||
|
|
@ -137,6 +145,7 @@ impl<T: 'static> Frontend<T> {
|
||||||
family_name_monospace: "",
|
family_name_monospace: "",
|
||||||
},
|
},
|
||||||
PathBuf::new(), //FIXME: pass from somewhere else
|
PathBuf::new(), //FIXME: pass from somewhere else
|
||||||
|
palette,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||||
|
|
@ -178,6 +187,7 @@ impl<T: 'static> Frontend<T> {
|
||||||
layout,
|
layout,
|
||||||
state,
|
state,
|
||||||
current_tab: None,
|
current_tab: None,
|
||||||
|
side_buttons: Vec::with_capacity(TabType::COUNT),
|
||||||
globals,
|
globals,
|
||||||
tasks,
|
tasks,
|
||||||
ticks: 0,
|
ticks: 0,
|
||||||
|
|
@ -193,7 +203,7 @@ impl<T: 'static> Frontend<T> {
|
||||||
toast_manager,
|
toast_manager,
|
||||||
window_audio_settings: WguiWindow::default(),
|
window_audio_settings: WguiWindow::default(),
|
||||||
view_audio_settings: None,
|
view_audio_settings: None,
|
||||||
executor: Rc::new(smol::LocalExecutor::new()),
|
executor: params.executor,
|
||||||
sounds_to_play: Vec::new(),
|
sounds_to_play: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -216,6 +226,7 @@ impl<T: 'static> Frontend<T> {
|
||||||
let path = match sound_type {
|
let path = match sound_type {
|
||||||
SoundType::Startup => "sound/startup.mp3",
|
SoundType::Startup => "sound/startup.mp3",
|
||||||
SoundType::Launch => "sound/app_start.mp3",
|
SoundType::Launch => "sound/app_start.mp3",
|
||||||
|
SoundType::Save => "sound/save.mp3",
|
||||||
};
|
};
|
||||||
|
|
||||||
// try loading a custom sound; if one doesn't exist (or it failed to load), use the built-in asset
|
// try loading a custom sound; if one doesn't exist (or it failed to load), use the built-in asset
|
||||||
|
|
@ -244,9 +255,6 @@ impl<T: 'static> Frontend<T> {
|
||||||
self.current_tab = Some(tab);
|
self.current_tab = Some(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process async runtime tasks
|
|
||||||
while self.executor.try_tick() {}
|
|
||||||
|
|
||||||
let res = self.tick(params)?;
|
let res = self.tick(params)?;
|
||||||
self.ticks += 1;
|
self.ticks += 1;
|
||||||
|
|
||||||
|
|
@ -350,8 +358,8 @@ impl<T: 'static> Frontend<T> {
|
||||||
(0.8666, 0.9333)
|
(0.8666, 0.9333)
|
||||||
};
|
};
|
||||||
|
|
||||||
rect.params.color.a = alpha1;
|
rect.params.color = rect.params.color.with_alpha(alpha1);
|
||||||
rect.params.color2.a = alpha2;
|
rect.params.color2 = rect.params.color2.with_alpha(alpha2);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -435,6 +443,15 @@ impl<T: 'static> Frontend<T> {
|
||||||
|
|
||||||
self.current_tab = Some(tab);
|
self.current_tab = Some(tab);
|
||||||
|
|
||||||
|
let mut common = CallbackDataCommon {
|
||||||
|
state: &self.layout.state,
|
||||||
|
alterables: &mut self.layout.alterables,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (t, btn) in self.side_buttons.iter() {
|
||||||
|
btn.set_sticky_state(&mut common, tab_type == *t);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -450,34 +467,29 @@ impl<T: 'static> Frontend<T> {
|
||||||
// ################################
|
// ################################
|
||||||
|
|
||||||
// "Home" side button
|
// "Home" side button
|
||||||
self.tasks.handle_button(
|
let btn = self.state.fetch_component_as::<ComponentButton>("btn_side_home")?;
|
||||||
&self.state.fetch_component_as::<ComponentButton>("btn_side_home")?,
|
self.tasks.handle_button(&btn, FrontendTask::SetTab(TabType::Home));
|
||||||
FrontendTask::SetTab(TabType::Home),
|
self.side_buttons.push((TabType::Home, btn));
|
||||||
);
|
|
||||||
|
|
||||||
// "Apps" side button
|
// "Apps" side button
|
||||||
self.tasks.handle_button(
|
let btn = self.state.fetch_component_as::<ComponentButton>("btn_side_apps")?;
|
||||||
&self.state.fetch_component_as::<ComponentButton>("btn_side_apps")?,
|
self.tasks.handle_button(&btn, FrontendTask::SetTab(TabType::Apps));
|
||||||
FrontendTask::SetTab(TabType::Apps),
|
self.side_buttons.push((TabType::Apps, btn));
|
||||||
);
|
|
||||||
|
|
||||||
// "Games" side button
|
// "Games" side button
|
||||||
self.tasks.handle_button(
|
let btn = self.state.fetch_component_as::<ComponentButton>("btn_side_games")?;
|
||||||
&self.state.fetch_component_as::<ComponentButton>("btn_side_games")?,
|
self.tasks.handle_button(&btn, FrontendTask::SetTab(TabType::Games));
|
||||||
FrontendTask::SetTab(TabType::Games),
|
self.side_buttons.push((TabType::Games, btn));
|
||||||
);
|
|
||||||
|
|
||||||
// "Monado side button"
|
// "Monado side button"
|
||||||
self.tasks.handle_button(
|
let btn = self.state.fetch_component_as::<ComponentButton>("btn_side_monado")?;
|
||||||
&self.state.fetch_component_as::<ComponentButton>("btn_side_monado")?,
|
self.tasks.handle_button(&btn, FrontendTask::SetTab(TabType::Monado));
|
||||||
FrontendTask::SetTab(TabType::Monado),
|
self.side_buttons.push((TabType::Monado, btn));
|
||||||
);
|
|
||||||
|
|
||||||
// "Settings" side button
|
// "Settings" side button
|
||||||
self.tasks.handle_button(
|
let btn = self.state.fetch_component_as::<ComponentButton>("btn_side_settings")?;
|
||||||
&self.state.fetch_component_as::<ComponentButton>("btn_side_settings")?,
|
self.tasks.handle_button(&btn, FrontendTask::SetTab(TabType::Settings));
|
||||||
FrontendTask::SetTab(TabType::Settings),
|
self.side_buttons.push((TabType::Settings, btn));
|
||||||
);
|
|
||||||
|
|
||||||
// ################################
|
// ################################
|
||||||
// BOTTOM BAR BUTTONS
|
// BOTTOM BAR BUTTONS
|
||||||
|
|
@ -539,7 +551,7 @@ impl<T: 'static> Frontend<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()> {
|
fn action_recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()> {
|
||||||
self.interface.recenter_playspace(data, RecenterMode::Recenter)?;
|
self.interface.playspace_task(data, DashPlayspaceTask::Recenter)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
mod assets;
|
mod assets;
|
||||||
pub mod frontend;
|
pub mod frontend;
|
||||||
mod tab;
|
mod tab;
|
||||||
|
mod test;
|
||||||
mod util;
|
mod util;
|
||||||
mod various;
|
mod various;
|
||||||
mod views;
|
mod views;
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,39 @@ use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::button::{ButtonClickCallback, ComponentButton},
|
components::button::{ButtonClickCallback, ComponentButton},
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
|
i18n::Translation,
|
||||||
layout::{WidgetID, WidgetPair},
|
layout::{WidgetID, WidgetPair},
|
||||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||||
|
task::Tasks,
|
||||||
};
|
};
|
||||||
use wlx_common::desktop_finder::DesktopEntry;
|
use wlx_common::{config::PinnedApp, desktop_finder::DesktopEntry};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::{Frontend, FrontendTasks},
|
frontend::{Frontend, FrontendTasks},
|
||||||
tab::{Tab, TabType},
|
tab::{Tab, TabType},
|
||||||
util::popup_manager::PopupHolder,
|
util::{popup_manager::PopupHolder, wgui_simple},
|
||||||
views::{self},
|
views::{self},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
parser_state: ParserState,
|
||||||
view_launcher: PopupHolder<views::app_launcher::View>,
|
view_launcher: PopupHolder<views::app_launcher::View>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TabApps<T> {
|
#[derive(Clone)]
|
||||||
#[allow(dead_code)]
|
enum Task {
|
||||||
parser_state: ParserState,
|
RefreshPinnedApps,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TabApps<T> {
|
||||||
state: Rc<RefCell<State>>,
|
state: Rc<RefCell<State>>,
|
||||||
app_list: AppList,
|
app_list: AppList,
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
|
|
||||||
|
pinned_apps_parent: WidgetID,
|
||||||
|
|
||||||
|
tasks: Tasks<Task>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tab<T> for TabApps<T> {
|
impl<T> Tab<T> for TabApps<T> {
|
||||||
|
|
@ -34,9 +44,15 @@ impl<T> Tab<T> for TabApps<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, frontend: &mut Frontend<T>, _time_ms: u32, data: &mut T) -> anyhow::Result<()> {
|
fn update(&mut self, frontend: &mut Frontend<T>, _time_ms: u32, data: &mut T) -> anyhow::Result<()> {
|
||||||
let state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
|
|
||||||
self.app_list.tick(frontend, &self.state, &mut self.parser_state)?;
|
self.app_list.tick(frontend, &self.tasks, &mut state, &self.state)?;
|
||||||
|
|
||||||
|
for task in self.tasks.drain() {
|
||||||
|
match task {
|
||||||
|
Task::RefreshPinnedApps => self.refresh_pinned_apps(&mut state, frontend, data)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state
|
state
|
||||||
.view_launcher
|
.view_launcher
|
||||||
|
|
@ -45,8 +61,85 @@ impl<T> Tab<T> for TabApps<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_entry_from_app_name<'a>(app_id: &str, entries: &'a [DesktopEntry]) -> Option<&'a DesktopEntry> {
|
||||||
|
entries.iter().find(|&entry| *entry.app_id == *app_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> TabApps<T> {
|
||||||
|
fn refresh_pinned_apps(&self, state: &mut State, frontend: &mut Frontend<T>, data: &mut T) -> anyhow::Result<()> {
|
||||||
|
frontend.layout.remove_children(self.pinned_apps_parent);
|
||||||
|
let globals = frontend.globals.clone();
|
||||||
|
|
||||||
|
let mut stale_entries = Vec::<Rc<str>>::new();
|
||||||
|
|
||||||
|
let mut pinned_desktop_entries = Vec::<(PinnedApp, &DesktopEntry)>::new();
|
||||||
|
|
||||||
|
// collect pinned desktop entries
|
||||||
|
{
|
||||||
|
let config = frontend.interface.general_config(data);
|
||||||
|
for pinned_app in &config.pinned_apps {
|
||||||
|
let Some(desktop_entry) = find_entry_from_app_name(&pinned_app.app_id, &self.app_list.all_entries) else {
|
||||||
|
stale_entries.push(pinned_app.app_id.clone());
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
pinned_desktop_entries.push((pinned_app.clone(), desktop_entry));
|
||||||
|
}
|
||||||
|
// cleanup:
|
||||||
|
// remove non-existent app ids from pinned apps
|
||||||
|
config.pinned_apps.retain(|pinned_app| {
|
||||||
|
for app_id in &stale_entries {
|
||||||
|
if *app_id == pinned_app.app_id {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if pinned_desktop_entries.is_empty() {
|
||||||
|
wgui_simple::create_label(
|
||||||
|
&mut frontend.layout,
|
||||||
|
self.pinned_apps_parent,
|
||||||
|
Translation::from_translation_key("EMPTY"),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mount pinned desktop entries
|
||||||
|
for (pinned_app, desktop_entry) in pinned_desktop_entries {
|
||||||
|
let tooltip_string = format!(
|
||||||
|
"{}\n{}\n{}",
|
||||||
|
pinned_app.compositor_mode.as_ref(),
|
||||||
|
pinned_app.orientation_mode.as_ref(),
|
||||||
|
pinned_app.res_mode.as_ref()
|
||||||
|
);
|
||||||
|
|
||||||
|
let button = mount_entry(
|
||||||
|
frontend,
|
||||||
|
&mut state.parser_state,
|
||||||
|
&doc_params(frontend.globals.clone()),
|
||||||
|
self.pinned_apps_parent,
|
||||||
|
desktop_entry,
|
||||||
|
Some(tooltip_string),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
button.on_click(on_app_click(
|
||||||
|
frontend.tasks.clone(),
|
||||||
|
self.tasks.clone(),
|
||||||
|
globals.clone(),
|
||||||
|
desktop_entry.clone(),
|
||||||
|
self.state.clone(),
|
||||||
|
Some(pinned_app.clone()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AppList {
|
struct AppList {
|
||||||
//data: Vec<ParserData>,
|
//data: Vec<ParserData>,
|
||||||
|
all_entries: Vec<DesktopEntry>,
|
||||||
entries_to_mount: VecDeque<DesktopEntry>,
|
entries_to_mount: VecDeque<DesktopEntry>,
|
||||||
list_parent: WidgetPair,
|
list_parent: WidgetPair,
|
||||||
prev_category_name: String,
|
prev_category_name: String,
|
||||||
|
|
@ -55,9 +148,11 @@ struct AppList {
|
||||||
// called after the user clicks any desktop entry
|
// called after the user clicks any desktop entry
|
||||||
fn on_app_click(
|
fn on_app_click(
|
||||||
frontend_tasks: FrontendTasks,
|
frontend_tasks: FrontendTasks,
|
||||||
|
tasks: Tasks<Task>,
|
||||||
globals: WguiGlobals,
|
globals: WguiGlobals,
|
||||||
entry: DesktopEntry,
|
entry: DesktopEntry,
|
||||||
state: Rc<RefCell<State>>,
|
state: Rc<RefCell<State>>,
|
||||||
|
pinned_app: Option<PinnedApp>,
|
||||||
) -> ButtonClickCallback {
|
) -> ButtonClickCallback {
|
||||||
Rc::new(move |_common, _evt| {
|
Rc::new(move |_common, _evt| {
|
||||||
views::app_launcher::mount_popup(
|
views::app_launcher::mount_popup(
|
||||||
|
|
@ -65,6 +160,8 @@ fn on_app_click(
|
||||||
globals.clone(),
|
globals.clone(),
|
||||||
entry.clone(),
|
entry.clone(),
|
||||||
state.borrow_mut().view_launcher.clone(),
|
state.borrow_mut().view_launcher.clone(),
|
||||||
|
tasks.make_callback_box(Task::RefreshPinnedApps),
|
||||||
|
pinned_app.clone(),
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
@ -81,20 +178,24 @@ fn doc_params(globals: WguiGlobals) -> ParseDocumentParams<'static> {
|
||||||
impl<T> TabApps<T> {
|
impl<T> TabApps<T> {
|
||||||
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, data: &mut T) -> anyhow::Result<Self> {
|
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, data: &mut T) -> anyhow::Result<Self> {
|
||||||
let globals = frontend.layout.state.globals.clone();
|
let globals = frontend.layout.state.globals.clone();
|
||||||
|
let parser_state = wgui::parser::parse_from_assets(&doc_params(globals.clone()), &mut frontend.layout, parent_id)?;
|
||||||
|
|
||||||
|
let app_list_parent = parser_state.fetch_widget(&frontend.layout.state, "app_list_parent")?;
|
||||||
|
let pinned_apps_parent = parser_state.fetch_widget(&frontend.layout.state, "pinned_apps_parent")?;
|
||||||
|
|
||||||
let state = Rc::new(RefCell::new(State {
|
let state = Rc::new(RefCell::new(State {
|
||||||
view_launcher: Default::default(),
|
view_launcher: Default::default(),
|
||||||
|
parser_state,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let parser_state = wgui::parser::parse_from_assets(&doc_params(globals.clone()), &mut frontend.layout, parent_id)?;
|
let entries: Vec<_> = frontend
|
||||||
let app_list_parent = parser_state.fetch_widget(&frontend.layout.state, "app_list_parent")?;
|
|
||||||
|
|
||||||
let mut entries_sorted: Vec<_> = frontend
|
|
||||||
.interface
|
.interface
|
||||||
.desktop_finder(data)
|
.desktop_finder(data)
|
||||||
.find_entries()
|
.find_entries()
|
||||||
.into_values()
|
.into_values()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let mut entries_sorted = entries.clone();
|
||||||
entries_sorted.sort_by(|a, b| {
|
entries_sorted.sort_by(|a, b| {
|
||||||
let cat_name_a = get_category_name(a);
|
let cat_name_a = get_category_name(a);
|
||||||
let cat_name_b = get_category_name(b);
|
let cat_name_b = get_category_name(b);
|
||||||
|
|
@ -102,16 +203,21 @@ impl<T> TabApps<T> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let app_list = AppList {
|
let app_list = AppList {
|
||||||
|
all_entries: entries,
|
||||||
entries_to_mount: entries_sorted.drain(..).collect(),
|
entries_to_mount: entries_sorted.drain(..).collect(),
|
||||||
list_parent: app_list_parent,
|
list_parent: app_list_parent,
|
||||||
prev_category_name: String::new(),
|
prev_category_name: String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let tasks = Tasks::<Task>::new();
|
||||||
|
tasks.push(Task::RefreshPinnedApps);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
app_list,
|
app_list,
|
||||||
parser_state,
|
|
||||||
state,
|
state,
|
||||||
|
tasks,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
|
pinned_apps_parent: pinned_apps_parent.id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -225,81 +331,93 @@ fn get_category_name(entry: &DesktopEntry) -> &str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppList {
|
fn mount_entry<T>(
|
||||||
fn mount_entry<T>(
|
frontend: &mut Frontend<T>,
|
||||||
&mut self,
|
parser_state: &mut ParserState,
|
||||||
frontend: &mut Frontend<T>,
|
doc_params: &ParseDocumentParams,
|
||||||
parser_state: &mut ParserState,
|
id_parent: WidgetID,
|
||||||
doc_params: &ParseDocumentParams,
|
entry: &DesktopEntry,
|
||||||
entry: &DesktopEntry,
|
tooltip: Option<String>,
|
||||||
) -> anyhow::Result<Rc<ComponentButton>> {
|
) -> anyhow::Result<Rc<ComponentButton>> {
|
||||||
let category_name = get_category_name(entry);
|
{
|
||||||
if category_name != self.prev_category_name {
|
let mut params = TemplateParams::new();
|
||||||
self.prev_category_name = String::from(category_name);
|
|
||||||
let mut params = TemplateParams::new();
|
|
||||||
params.insert("text", category_name);
|
|
||||||
|
|
||||||
parser_state.realize_template(
|
if let Some(tooltip) = tooltip {
|
||||||
doc_params,
|
params.insert_str("tooltip", tooltip);
|
||||||
"CategoryText",
|
};
|
||||||
&mut frontend.layout,
|
|
||||||
self.list_parent.id,
|
|
||||||
params,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
// entry icon
|
||||||
let mut params = TemplateParams::new();
|
params.insert_rc(
|
||||||
|
"src_ext",
|
||||||
|
entry
|
||||||
|
.icon_path
|
||||||
|
.as_ref()
|
||||||
|
.map_or_else(|| "".into(), |icon_path| icon_path.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
// entry icon
|
// entry fallback (question mark) icon
|
||||||
params.insert_rc(
|
params.insert(
|
||||||
"src_ext",
|
"src",
|
||||||
entry
|
if entry.icon_path.is_none() {
|
||||||
.icon_path
|
"dashboard/terminal.svg"
|
||||||
.as_ref()
|
} else {
|
||||||
.map_or_else(|| "".into(), |icon_path| icon_path.clone()),
|
""
|
||||||
);
|
},
|
||||||
|
);
|
||||||
|
params.insert("name", &entry.app_name);
|
||||||
|
|
||||||
// entry fallback (question mark) icon
|
let data = parser_state.realize_template(doc_params, "AppEntry", &mut frontend.layout, id_parent, params)?;
|
||||||
params.insert(
|
|
||||||
"src",
|
|
||||||
if entry.icon_path.is_none() {
|
|
||||||
"dashboard/terminal.svg"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
);
|
|
||||||
params.insert("name", &entry.app_name);
|
|
||||||
|
|
||||||
let data = parser_state.realize_template(
|
data.fetch_component_as::<ComponentButton>("button")
|
||||||
doc_params,
|
|
||||||
"AppEntry",
|
|
||||||
&mut frontend.layout,
|
|
||||||
self.list_parent.id,
|
|
||||||
params,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
data.fetch_component_as::<ComponentButton>("button")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppList {
|
||||||
fn tick<T>(
|
fn tick<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend<T>,
|
frontend: &mut Frontend<T>,
|
||||||
state: &Rc<RefCell<State>>,
|
tasks: &Tasks<Task>,
|
||||||
parser_state: &mut ParserState,
|
state: &mut State,
|
||||||
|
rc_state: &Rc<RefCell<State>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let parser_state = &mut state.parser_state;
|
||||||
|
|
||||||
// load 30 entries for a single frame at most
|
// load 30 entries for a single frame at most
|
||||||
for _ in 0..30 {
|
for _ in 0..30 {
|
||||||
if let Some(entry) = self.entries_to_mount.pop_front() {
|
if let Some(entry) = self.entries_to_mount.pop_front() {
|
||||||
let globals = frontend.layout.state.globals.clone();
|
let globals = frontend.layout.state.globals.clone();
|
||||||
let button = self.mount_entry(frontend, parser_state, &doc_params(globals.clone()), &entry)?;
|
|
||||||
|
let category_name = get_category_name(&entry);
|
||||||
|
if category_name != self.prev_category_name {
|
||||||
|
self.prev_category_name = String::from(category_name);
|
||||||
|
let mut params = TemplateParams::new();
|
||||||
|
params.insert("text", category_name);
|
||||||
|
|
||||||
|
parser_state.realize_template(
|
||||||
|
&doc_params(globals.clone()),
|
||||||
|
"CategoryText",
|
||||||
|
&mut frontend.layout,
|
||||||
|
self.list_parent.id,
|
||||||
|
params,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let button = mount_entry(
|
||||||
|
frontend,
|
||||||
|
parser_state,
|
||||||
|
&doc_params(globals.clone()),
|
||||||
|
self.list_parent.id,
|
||||||
|
&entry,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
button.on_click(on_app_click(
|
button.on_click(on_app_click(
|
||||||
frontend.tasks.clone(),
|
frontend.tasks.clone(),
|
||||||
|
tasks.clone(),
|
||||||
globals.clone(),
|
globals.clone(),
|
||||||
entry.clone(),
|
entry.clone(),
|
||||||
state.clone(),
|
rc_state.clone(),
|
||||||
|
None,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,23 @@ use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::button::ComponentButton,
|
components::button::ComponentButton,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
layout::WidgetID,
|
layout::{Layout, WidgetID},
|
||||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||||
|
taffy::{self, style_helpers::length},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
|
widget::div::WidgetDiv,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::{Frontend, FrontendTask},
|
frontend::{Frontend, FrontendTask},
|
||||||
tab::{Tab, TabType},
|
tab::{Tab, TabType},
|
||||||
|
util::cached_fetcher,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[allow(clippy::enum_variant_names)]
|
#[allow(clippy::enum_variant_names)]
|
||||||
enum Task {}
|
enum Task {
|
||||||
|
SetSupporters(cached_fetcher::Supporters),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct TabDonate<T> {
|
pub struct TabDonate<T> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -24,6 +28,8 @@ pub struct TabDonate<T> {
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
tasks: Tasks<Task>,
|
tasks: Tasks<Task>,
|
||||||
|
|
||||||
|
id_current_supporters: WidgetID,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tab<T> for TabDonate<T> {
|
impl<T> Tab<T> for TabDonate<T> {
|
||||||
|
|
@ -31,10 +37,14 @@ impl<T> Tab<T> for TabDonate<T> {
|
||||||
TabType::Donate
|
TabType::Donate
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, _frontend: &mut Frontend<T>, _time_ms: u32, _user_data: &mut T) -> anyhow::Result<()> {
|
fn update(&mut self, frontend: &mut Frontend<T>, _time_ms: u32, _user_data: &mut T) -> anyhow::Result<()> {
|
||||||
// for task in self.tasks.drain() {
|
while !self.tasks.is_empty() {
|
||||||
// match task {}
|
for task in self.tasks.drain() {
|
||||||
// }
|
match task {
|
||||||
|
Task::SetSupporters(supporters) => self.set_supporters(&mut frontend.layout, supporters)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -48,9 +58,62 @@ fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn request_supporters(tasks: Tasks<Task>) {
|
||||||
|
if let Some(supporters) = cached_fetcher::request_supporters().await {
|
||||||
|
tasks.push(Task::SetSupporters(supporters))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> TabDonate<T> {
|
impl<T> TabDonate<T> {
|
||||||
|
fn set_supporters(&mut self, layout: &mut Layout, supporters: cached_fetcher::Supporters) -> anyhow::Result<()> {
|
||||||
|
let globals = layout.state.globals.clone();
|
||||||
|
layout.remove_children(self.id_current_supporters);
|
||||||
|
|
||||||
|
let mut current_tier = None;
|
||||||
|
let mut tier_parent = WidgetID::default();
|
||||||
|
|
||||||
|
for supporter in &supporters.supporters {
|
||||||
|
if Some(supporter.tier) != current_tier {
|
||||||
|
current_tier = Some(supporter.tier);
|
||||||
|
|
||||||
|
let mut params = TemplateParams::new();
|
||||||
|
params.insert_str("text", supporter.tier.pretty_str());
|
||||||
|
params.insert("color", supporter.tier.color_str());
|
||||||
|
self.state.realize_template(
|
||||||
|
&doc_params(&globals),
|
||||||
|
"TierCell",
|
||||||
|
layout,
|
||||||
|
self.id_current_supporters,
|
||||||
|
params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
tier_parent = layout
|
||||||
|
.add_child(
|
||||||
|
self.id_current_supporters,
|
||||||
|
WidgetDiv::create(),
|
||||||
|
taffy::Style {
|
||||||
|
gap: length(8.0_f32),
|
||||||
|
flex_wrap: taffy::FlexWrap::Wrap,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
.0
|
||||||
|
.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut params = TemplateParams::new();
|
||||||
|
params.insert("username", &supporter.username);
|
||||||
|
self
|
||||||
|
.state
|
||||||
|
.realize_template(&doc_params(&globals), "SupporterCell", layout, tier_parent, params)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, _data: &mut T) -> anyhow::Result<Self> {
|
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, _data: &mut T) -> anyhow::Result<Self> {
|
||||||
let state = wgui::parser::parse_from_assets(&doc_params(&frontend.globals), &mut frontend.layout, parent_id)?;
|
let state = wgui::parser::parse_from_assets(&doc_params(&frontend.globals), &mut frontend.layout, parent_id)?;
|
||||||
|
let id_current_supporters = state.get_widget_id("current_supporters")?;
|
||||||
|
|
||||||
frontend.tasks.handle_button(
|
frontend.tasks.handle_button(
|
||||||
&state.fetch_component_as::<ComponentButton>("btn_donate")?,
|
&state.fetch_component_as::<ComponentButton>("btn_donate")?,
|
||||||
|
|
@ -59,10 +122,13 @@ impl<T> TabDonate<T> {
|
||||||
|
|
||||||
let tasks = Tasks::<Task>::new();
|
let tasks = Tasks::<Task>::new();
|
||||||
|
|
||||||
|
frontend.executor.spawn(request_supporters(tasks.clone())).detach();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
tasks,
|
tasks,
|
||||||
|
id_current_supporters,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
use std::marker::PhantomData;
|
use std::{marker::PhantomData, rc::Rc};
|
||||||
|
|
||||||
use wgui::{
|
use wgui::{
|
||||||
|
animation::{Animation, AnimationEasing},
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::button::ComponentButton,
|
color::{WguiColor, WguiColorName, WguiNamedColor},
|
||||||
|
components::{ComponentTrait, button::ComponentButton},
|
||||||
event::CallbackDataCommon,
|
event::CallbackDataCommon,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Widget, WidgetID},
|
layout::{LayoutTask, LayoutTasks, Widget, WidgetID},
|
||||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||||
widget::label::WidgetLabel,
|
widget::label::WidgetLabel,
|
||||||
};
|
};
|
||||||
|
|
@ -14,6 +16,7 @@ use wlx_common::config::GeneralConfig;
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::{Frontend, FrontendTask},
|
frontend::{Frontend, FrontendTask},
|
||||||
tab::{Tab, TabType},
|
tab::{Tab, TabType},
|
||||||
|
util::cached_fetcher,
|
||||||
various,
|
various,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -29,14 +32,101 @@ impl<T> Tab<T> for TabHome<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_label_hello(common: &mut CallbackDataCommon, label_hello: Widget, config: &GeneralConfig) {
|
fn get_supporter_anim(
|
||||||
let mut username = various::get_username();
|
btn: Rc<ComponentButton>,
|
||||||
// first character as uppercase
|
tasks: LayoutTasks,
|
||||||
if let Some(first) = username.chars().next() {
|
supporters: Rc<cached_fetcher::Supporters>,
|
||||||
let first = first.to_uppercase().to_string();
|
prev_supporter_name: String,
|
||||||
username.replace_range(0..1, &first);
|
) -> Animation {
|
||||||
|
let username = loop {
|
||||||
|
let total_tickets: u32 = supporters.supporters.iter().map(|s| s.tickets()).sum();
|
||||||
|
let jackpot = rand::random_range(0..total_tickets);
|
||||||
|
let mut cumulative = 0u32;
|
||||||
|
let random_supporter = supporters
|
||||||
|
.supporters
|
||||||
|
.iter()
|
||||||
|
.find(|s| {
|
||||||
|
cumulative += s.tickets();
|
||||||
|
cumulative >= jackpot
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let username = random_supporter.username.clone();
|
||||||
|
if username != prev_supporter_name {
|
||||||
|
break username;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const FADE_SPEED: f32 = 10.0;
|
||||||
|
|
||||||
|
Animation::new_ex(
|
||||||
|
btn.base().get_id(),
|
||||||
|
1234,
|
||||||
|
480,
|
||||||
|
AnimationEasing::Linear,
|
||||||
|
Box::new(move |common, data| {
|
||||||
|
let opacity_in = f32::clamp(data.pos * FADE_SPEED, 0.0, 1.0);
|
||||||
|
let opacity_out = f32::clamp((1.0 - data.pos) * FADE_SPEED, 0.0, 1.0);
|
||||||
|
let opacity = f32::min(opacity_in, opacity_out);
|
||||||
|
|
||||||
|
btn.set_text_color(
|
||||||
|
common,
|
||||||
|
WguiColor::Named(WguiNamedColor::with_alpha(WguiColorName::OnBackgroundVariant, opacity)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// first iter
|
||||||
|
if data.pos == 0.0 {
|
||||||
|
let translation_key = match rand::random::<u8>() {
|
||||||
|
0..=15 => "DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE",
|
||||||
|
16..=70 => "DONATE.BROUGHT_TO_YOU_VARIANTS_RARE",
|
||||||
|
71..=u8::MAX => "DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN",
|
||||||
|
};
|
||||||
|
|
||||||
|
let translated = common.globals().i18n_builtin.translate(translation_key);
|
||||||
|
let variants = translated.split('|').collect::<Vec<&str>>();
|
||||||
|
let variant = variants[rand::random_range(0..variants.len() - 1)];
|
||||||
|
|
||||||
|
btn.set_text(
|
||||||
|
common,
|
||||||
|
Translation::from_raw_text_string(variant.replace("{USER}", &username)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// last iter
|
||||||
|
if data.pos == 1.0 {
|
||||||
|
// infinitely looped animation, re-trigger it.
|
||||||
|
tasks.push(LayoutTask::PlayAnimation(get_supporter_anim(
|
||||||
|
btn.clone(),
|
||||||
|
tasks.clone(),
|
||||||
|
supporters.clone(),
|
||||||
|
username.clone(), /* prev supporter name */
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn config_supporters(btn: Rc<ComponentButton>, tasks: LayoutTasks) {
|
||||||
|
let Some(supporters) = cached_fetcher::request_supporters().await else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if supporters.supporters.len() <= 2 {
|
||||||
|
return; // Welp.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let supporters = Rc::new(supporters);
|
||||||
|
|
||||||
|
tasks.push(LayoutTask::PlayAnimation(get_supporter_anim(
|
||||||
|
btn,
|
||||||
|
tasks.clone(),
|
||||||
|
supporters,
|
||||||
|
String::new(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_label_hello(common: &mut CallbackDataCommon, label_hello: Widget, config: &GeneralConfig) {
|
||||||
|
let username = wlx_common::locale::capitalize_string(&various::get_username());
|
||||||
|
|
||||||
let translated = if !config.hide_username {
|
let translated = if !config.hide_username {
|
||||||
common.i18n().translate_and_replace("HELLO_USER", ("{USER}", &username))
|
common.i18n().translate_and_replace("HELLO_USER", ("{USER}", &username))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -66,6 +156,8 @@ impl<T> TabHome<T> {
|
||||||
frontend.interface.general_config(data),
|
frontend.interface.general_config(data),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let btn_supporter = state.fetch_component_as::<ComponentButton>("btn_supporter")?;
|
||||||
|
|
||||||
let btn_apps = state.fetch_component_as::<ComponentButton>("btn_apps")?;
|
let btn_apps = state.fetch_component_as::<ComponentButton>("btn_apps")?;
|
||||||
let btn_games = state.fetch_component_as::<ComponentButton>("btn_games")?;
|
let btn_games = state.fetch_component_as::<ComponentButton>("btn_games")?;
|
||||||
let btn_monado = state.fetch_component_as::<ComponentButton>("btn_monado")?;
|
let btn_monado = state.fetch_component_as::<ComponentButton>("btn_monado")?;
|
||||||
|
|
@ -74,14 +166,20 @@ impl<T> TabHome<T> {
|
||||||
let btn_donate = state.fetch_component_as::<ComponentButton>("btn_donate")?;
|
let btn_donate = state.fetch_component_as::<ComponentButton>("btn_donate")?;
|
||||||
let btn_website = state.fetch_component_as::<ComponentButton>("btn_website")?;
|
let btn_website = state.fetch_component_as::<ComponentButton>("btn_website")?;
|
||||||
|
|
||||||
let tasks = &mut frontend.tasks;
|
let f_tasks = &mut frontend.tasks;
|
||||||
tasks.handle_button(&btn_apps, FrontendTask::SetTab(TabType::Apps));
|
f_tasks.handle_button(&btn_apps, FrontendTask::SetTab(TabType::Apps));
|
||||||
tasks.handle_button(&btn_games, FrontendTask::SetTab(TabType::Games));
|
f_tasks.handle_button(&btn_games, FrontendTask::SetTab(TabType::Games));
|
||||||
tasks.handle_button(&btn_monado, FrontendTask::SetTab(TabType::Monado));
|
f_tasks.handle_button(&btn_monado, FrontendTask::SetTab(TabType::Monado));
|
||||||
tasks.handle_button(&btn_settings, FrontendTask::SetTab(TabType::Settings));
|
f_tasks.handle_button(&btn_settings, FrontendTask::SetTab(TabType::Settings));
|
||||||
tasks.handle_button(&btn_welcome_screen, FrontendTask::SetTab(TabType::Welcome));
|
f_tasks.handle_button(&btn_welcome_screen, FrontendTask::SetTab(TabType::Welcome));
|
||||||
tasks.handle_button(&btn_donate, FrontendTask::SetTab(TabType::Donate));
|
f_tasks.handle_button(&btn_donate, FrontendTask::SetTab(TabType::Donate));
|
||||||
tasks.handle_button(&btn_website, FrontendTask::OpenURL("https://wayvr.org".into()));
|
f_tasks.handle_button(&btn_supporter, FrontendTask::SetTab(TabType::Donate));
|
||||||
|
f_tasks.handle_button(&btn_website, FrontendTask::OpenURL("https://wayvr.org".into()));
|
||||||
|
|
||||||
|
frontend
|
||||||
|
.executor
|
||||||
|
.spawn(config_supporters(btn_supporter, frontend.layout.tasks.clone()))
|
||||||
|
.detach();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use strum::EnumCount;
|
||||||
|
|
||||||
use crate::frontend::Frontend;
|
use crate::frontend::Frontend;
|
||||||
|
|
||||||
pub mod apps;
|
pub mod apps;
|
||||||
|
|
@ -8,7 +10,7 @@ pub mod monado;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod welcome;
|
pub mod welcome;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, EnumCount)]
|
||||||
pub enum TabType {
|
pub enum TabType {
|
||||||
Home,
|
Home,
|
||||||
Apps,
|
Apps,
|
||||||
|
|
@ -22,7 +24,7 @@ pub enum TabType {
|
||||||
impl TabType {
|
impl TabType {
|
||||||
pub fn get_preferred_padding(&self) -> f32 {
|
pub fn get_preferred_padding(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
TabType::Welcome | TabType::Donate => 0.0,
|
TabType::Welcome => 0.0,
|
||||||
_ => 16.0,
|
_ => 16.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,16 @@ use crate::{
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum TabNameEnum {
|
enum TabNameEnum {
|
||||||
GeneralSettings,
|
|
||||||
ProcessList,
|
ProcessList,
|
||||||
|
GeneralSettings,
|
||||||
DebugTimings,
|
DebugTimings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TabNameEnum {
|
impl TabNameEnum {
|
||||||
fn from_string(s: &str) -> Option<Self> {
|
fn from_string(s: &str) -> Option<Self> {
|
||||||
match s {
|
match s {
|
||||||
"general_settings" => Some(TabNameEnum::GeneralSettings),
|
|
||||||
"process_list" => Some(TabNameEnum::ProcessList),
|
"process_list" => Some(TabNameEnum::ProcessList),
|
||||||
|
"general_settings" => Some(TabNameEnum::GeneralSettings),
|
||||||
"debug_timings" => Some(TabNameEnum::DebugTimings),
|
"debug_timings" => Some(TabNameEnum::DebugTimings),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ enum Task {
|
||||||
|
|
||||||
// `ProcessList` tab
|
// `ProcessList` tab
|
||||||
ProcessListRefresh,
|
ProcessListRefresh,
|
||||||
ProcessListFocusClient(String),
|
ProcessListFocusClient(i64),
|
||||||
|
|
||||||
// `DebugTimings` tab
|
// `DebugTimings` tab
|
||||||
DebugTimingsRefreshSessionList,
|
DebugTimingsRefreshSessionList,
|
||||||
|
|
@ -126,8 +126,8 @@ struct SubtabDebugTimings {
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum Subtab {
|
enum Subtab {
|
||||||
Empty,
|
Empty,
|
||||||
GeneralSettings(SubtabGeneralSettings),
|
|
||||||
ProcessList(SubtabProcessList),
|
ProcessList(SubtabProcessList),
|
||||||
|
GeneralSettings(SubtabGeneralSettings),
|
||||||
DebugTimings(SubtabDebugTimings),
|
DebugTimings(SubtabDebugTimings),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,9 +157,9 @@ impl<T> Tab<T> for TabMonado<T> {
|
||||||
process_list.refresh(frontend, data, &self.tasks)?;
|
process_list.refresh(frontend, data, &self.tasks)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task::ProcessListFocusClient(client_name) => {
|
Task::ProcessListFocusClient(client_id) => {
|
||||||
if let Subtab::ProcessList(process_list) = &mut self.subtab {
|
if let Subtab::ProcessList(process_list) = &mut self.subtab {
|
||||||
process_list.focus_client(frontend, data, client_name, &self.tasks)?;
|
process_list.focus_client(frontend, data, client_id, &self.tasks)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task::DebugTimingsRefreshSessionList => {
|
Task::DebugTimingsRefreshSessionList => {
|
||||||
|
|
@ -184,6 +184,10 @@ impl<T> Tab<T> for TabMonado<T> {
|
||||||
Task::SetTab(tab) => {
|
Task::SetTab(tab) => {
|
||||||
frontend.layout.remove_children(self.id_content);
|
frontend.layout.remove_children(self.id_content);
|
||||||
match tab {
|
match tab {
|
||||||
|
TabNameEnum::ProcessList => {
|
||||||
|
self.tasks.push(Task::ProcessListRefresh);
|
||||||
|
self.subtab = Subtab::ProcessList(SubtabProcessList::new(self.id_content, frontend)?)
|
||||||
|
}
|
||||||
TabNameEnum::GeneralSettings => {
|
TabNameEnum::GeneralSettings => {
|
||||||
self.subtab = Subtab::GeneralSettings(SubtabGeneralSettings::new(
|
self.subtab = Subtab::GeneralSettings(SubtabGeneralSettings::new(
|
||||||
self.id_content,
|
self.id_content,
|
||||||
|
|
@ -192,10 +196,6 @@ impl<T> Tab<T> for TabMonado<T> {
|
||||||
&self.tasks,
|
&self.tasks,
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
TabNameEnum::ProcessList => {
|
|
||||||
self.tasks.push(Task::ProcessListRefresh);
|
|
||||||
self.subtab = Subtab::ProcessList(SubtabProcessList::new(self.id_content, frontend)?)
|
|
||||||
}
|
|
||||||
TabNameEnum::DebugTimings => {
|
TabNameEnum::DebugTimings => {
|
||||||
self.subtab = Subtab::DebugTimings(SubtabDebugTimings::new(self.id_content, frontend, &self.tasks)?)
|
self.subtab = Subtab::DebugTimings(SubtabDebugTimings::new(self.id_content, frontend, &self.tasks)?)
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +206,6 @@ impl<T> Tab<T> for TabMonado<T> {
|
||||||
|
|
||||||
match &mut self.subtab {
|
match &mut self.subtab {
|
||||||
Subtab::Empty => {}
|
Subtab::Empty => {}
|
||||||
Subtab::GeneralSettings(_) => {}
|
|
||||||
Subtab::ProcessList(_) => {
|
Subtab::ProcessList(_) => {
|
||||||
// every few seconds
|
// every few seconds
|
||||||
if let Subtab::ProcessList(_) = &self.subtab
|
if let Subtab::ProcessList(_) = &self.subtab
|
||||||
|
|
@ -215,6 +214,7 @@ impl<T> Tab<T> for TabMonado<T> {
|
||||||
self.tasks.push(Task::ProcessListRefresh);
|
self.tasks.push(Task::ProcessListRefresh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Subtab::GeneralSettings(_) => {}
|
||||||
Subtab::DebugTimings(timings) => {
|
Subtab::DebugTimings(timings) => {
|
||||||
timings.update(&self.tasks, data, frontend)?;
|
timings.update(&self.tasks, data, frontend)?;
|
||||||
}
|
}
|
||||||
|
|
@ -676,10 +676,10 @@ impl SubtabProcessList {
|
||||||
let checkbox = state_cell.fetch_component_as::<ComponentCheckbox>("checkbox")?;
|
let checkbox = state_cell.fetch_component_as::<ComponentCheckbox>("checkbox")?;
|
||||||
checkbox.on_toggle({
|
checkbox.on_toggle({
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
let client_name = client.name.clone();
|
let client_id = client.id;
|
||||||
Box::new(move |_common, e| {
|
Box::new(move |_common, e| {
|
||||||
if e.checked {
|
if e.checked {
|
||||||
tasks.push(Task::ProcessListFocusClient(client_name.clone()));
|
tasks.push(Task::ProcessListFocusClient(client_id));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
@ -694,10 +694,10 @@ impl SubtabProcessList {
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend<T>,
|
frontend: &mut Frontend<T>,
|
||||||
data: &mut T,
|
data: &mut T,
|
||||||
name: String,
|
client_id: i64,
|
||||||
tasks: &Tasks<Task>,
|
tasks: &Tasks<Task>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
frontend.interface.monado_client_focus(data, &name)?;
|
frontend.interface.monado_client_focus(data, client_id)?;
|
||||||
tasks.push(Task::ProcessListRefresh);
|
tasks.push(Task::ProcessListRefresh);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use wgui::{
|
||||||
widget::label::WidgetLabel,
|
widget::label::WidgetLabel,
|
||||||
windowing::context_menu,
|
windowing::context_menu,
|
||||||
};
|
};
|
||||||
use wlx_common::config::GeneralConfig;
|
use wlx_common::{DesktopBackend, XrBackend, config::GeneralConfig, dash_interface::InterfaceFeats};
|
||||||
|
|
||||||
pub fn options_category(
|
pub fn options_category(
|
||||||
mp: &mut MacroParams,
|
mp: &mut MacroParams,
|
||||||
|
|
@ -272,6 +272,7 @@ where
|
||||||
|
|
||||||
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
btn.on_click(Rc::new({
|
btn.on_click(Rc::new({
|
||||||
|
let feats = mp.feats;
|
||||||
let tasks = mp.tasks.clone();
|
let tasks = mp.tasks.clone();
|
||||||
move |_common, e: ButtonClickEvent| {
|
move |_common, e: ButtonClickEvent| {
|
||||||
tasks.push(Task::OpenContextMenu(
|
tasks.push(Task::OpenContextMenu(
|
||||||
|
|
@ -282,6 +283,18 @@ where
|
||||||
if item.get_bool("Hidden").unwrap_or(false) {
|
if item.get_bool("Hidden").unwrap_or(false) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
if item
|
||||||
|
.get_str("Backend")
|
||||||
|
.is_some_and(|x| XrBackend::try_from(x).unwrap() != feats.xr_backend)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if item
|
||||||
|
.get_str("Desktop")
|
||||||
|
.is_some_and(|x| DesktopBackend::try_from(x).unwrap() != feats.desktop_backend)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let value = item.as_ref();
|
let value = item.as_ref();
|
||||||
let title = SettingType::get_enum_title_inner(*item);
|
let title = SettingType::get_enum_title_inner(*item);
|
||||||
|
|
@ -336,6 +349,36 @@ pub fn options_danger_button(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn options_button(
|
||||||
|
mp: &mut MacroParams,
|
||||||
|
parent: WidgetID,
|
||||||
|
translation: &str,
|
||||||
|
icon: &str,
|
||||||
|
task: Task,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let id = mp.idx.to_string();
|
||||||
|
mp.idx += 1;
|
||||||
|
|
||||||
|
let mut params = TemplateParams::new();
|
||||||
|
params.insert("id", &id);
|
||||||
|
params.insert("translation", translation);
|
||||||
|
params.insert("icon", icon);
|
||||||
|
|
||||||
|
mp.parser_state
|
||||||
|
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, parent, params)?;
|
||||||
|
|
||||||
|
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
let tasks = mp.tasks.clone();
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks.push(task.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn options_autostart_app(
|
pub fn options_autostart_app(
|
||||||
mp: &mut MacroParams,
|
mp: &mut MacroParams,
|
||||||
parent: WidgetID,
|
parent: WidgetID,
|
||||||
|
|
@ -374,4 +417,5 @@ pub struct MacroParams<'a> {
|
||||||
pub config: &'a mut GeneralConfig,
|
pub config: &'a mut GeneralConfig,
|
||||||
pub tasks: Tasks<settings::Task>,
|
pub tasks: Tasks<settings::Task>,
|
||||||
pub idx: usize,
|
pub idx: usize,
|
||||||
|
pub feats: InterfaceFeats,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@ use std::{marker::PhantomData, rc::Rc, str::FromStr};
|
||||||
use strum::{AsRefStr, EnumProperty, EnumString};
|
use strum::{AsRefStr, EnumProperty, EnumString};
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
|
color::WguiColorName,
|
||||||
components::tabs::ComponentTabs,
|
components::tabs::ComponentTabs,
|
||||||
drawing,
|
|
||||||
event::StyleSetRequest,
|
event::StyleSetRequest,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
log::LogErr,
|
log::LogErr,
|
||||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||||
renderer_vk::text::{FontWeight, TextStyle},
|
renderer_vk::text::{FontWeight, TextStyle, WguiTextShadow},
|
||||||
taffy::{self, prelude::length},
|
taffy::{self, prelude::length},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
widget::{
|
widget::{
|
||||||
|
|
@ -23,7 +23,7 @@ use wgui::{
|
||||||
use wlx_common::{
|
use wlx_common::{
|
||||||
config::GeneralConfig,
|
config::GeneralConfig,
|
||||||
config_io::ConfigRoot,
|
config_io::ConfigRoot,
|
||||||
dash_interface::{ConfigChangeKind, InterfaceFeats, RecenterMode},
|
dash_interface::{ConfigChangeKind, DashPlayspaceTask, InterfaceFeats},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -43,7 +43,7 @@ mod tab_space_drag;
|
||||||
mod tab_troubleshooting;
|
mod tab_troubleshooting;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum TabNameEnum {
|
pub(crate) enum TabNameEnum {
|
||||||
AutostartApps,
|
AutostartApps,
|
||||||
Controls,
|
Controls,
|
||||||
Features,
|
Features,
|
||||||
|
|
@ -71,14 +71,16 @@ impl TabNameEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Task {
|
pub(crate) enum Task {
|
||||||
ClearPipewireTokens,
|
ClearPipewireTokens,
|
||||||
ClearSavedState,
|
ClearSavedState,
|
||||||
DeleteAllConfigs,
|
DeleteAllConfigs,
|
||||||
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
||||||
RemoveAutostartApp(Rc<str>),
|
RemoveAutostartApp(Rc<str>),
|
||||||
ResetPlayspace,
|
ResetPlayspace,
|
||||||
|
ResetPlayspaceCenter,
|
||||||
RestartSoftware,
|
RestartSoftware,
|
||||||
|
SavePlayspaceCenter,
|
||||||
SetTab(TabNameEnum),
|
SetTab(TabNameEnum),
|
||||||
SettingUpdated(SettingType),
|
SettingUpdated(SettingType),
|
||||||
UpdateBool(SettingType, bool),
|
UpdateBool(SettingType, bool),
|
||||||
|
|
@ -200,8 +202,18 @@ impl<T> Tab<T> for TabSettings<T> {
|
||||||
std::fs::remove_dir_all(&path)?;
|
std::fs::remove_dir_all(&path)?;
|
||||||
std::fs::create_dir(&path)?;
|
std::fs::create_dir(&path)?;
|
||||||
}
|
}
|
||||||
|
Task::SavePlayspaceCenter => {
|
||||||
|
frontend.interface.playspace_task(data, DashPlayspaceTask::SaveCenter)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Task::ResetPlayspaceCenter => {
|
||||||
|
frontend
|
||||||
|
.interface
|
||||||
|
.playspace_task(data, DashPlayspaceTask::ResetCenter)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
Task::ResetPlayspace => {
|
Task::ResetPlayspace => {
|
||||||
frontend.interface.recenter_playspace(data, RecenterMode::Reset)?;
|
frontend.interface.playspace_task(data, DashPlayspaceTask::Reset)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Task::RestartSoftware => {
|
Task::RestartSoftware => {
|
||||||
|
|
@ -291,7 +303,7 @@ impl<T> Tab<T> for TabSettings<T> {
|
||||||
// Sorted alphabetically
|
// Sorted alphabetically
|
||||||
#[allow(clippy::enum_variant_names)]
|
#[allow(clippy::enum_variant_names)]
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, AsRefStr, EnumString)]
|
#[derive(Clone, Copy, Eq, PartialEq, AsRefStr, EnumString)]
|
||||||
enum SettingType {
|
pub(crate) enum SettingType {
|
||||||
AllowSliding,
|
AllowSliding,
|
||||||
BlockGameInput,
|
BlockGameInput,
|
||||||
BlockGameInputIgnoreWatch,
|
BlockGameInputIgnoreWatch,
|
||||||
|
|
@ -299,12 +311,19 @@ enum SettingType {
|
||||||
CaptureMethod,
|
CaptureMethod,
|
||||||
ClickFreezeTimeMs,
|
ClickFreezeTimeMs,
|
||||||
Clock12h,
|
Clock12h,
|
||||||
|
DefaultCurvature,
|
||||||
|
DefaultOpacity,
|
||||||
|
DefaultOverlayScale,
|
||||||
|
DefaultPositioning,
|
||||||
DoubleCursorFix,
|
DoubleCursorFix,
|
||||||
|
EnableWatch,
|
||||||
FocusFollowsMouseMode,
|
FocusFollowsMouseMode,
|
||||||
GridOpacity,
|
GridOpacity,
|
||||||
|
HandsfreeAltTab,
|
||||||
HandsfreePointer,
|
HandsfreePointer,
|
||||||
HideGrabHelp,
|
HideGrabHelp,
|
||||||
HideUsername,
|
HideUsername,
|
||||||
|
InputCaptureMethod,
|
||||||
InputEmulationMethod,
|
InputEmulationMethod,
|
||||||
InvertScrollDirectionX,
|
InvertScrollDirectionX,
|
||||||
InvertScrollDirectionY,
|
InvertScrollDirectionY,
|
||||||
|
|
@ -315,13 +334,15 @@ enum SettingType {
|
||||||
LongPressDuration,
|
LongPressDuration,
|
||||||
NotificationsEnabled,
|
NotificationsEnabled,
|
||||||
NotificationsSoundEnabled,
|
NotificationsSoundEnabled,
|
||||||
DefaultOverlayScale,
|
|
||||||
OpaqueBackground,
|
OpaqueBackground,
|
||||||
|
MouseAcceleration,
|
||||||
PointerLerpFactor,
|
PointerLerpFactor,
|
||||||
|
MouseSpeed,
|
||||||
ScreenRenderDown,
|
ScreenRenderDown,
|
||||||
ScrollSpeed,
|
ScrollSpeed,
|
||||||
EnableWatch,
|
SnapAngleDeg,
|
||||||
SetsOnWatch,
|
SetsOnWatch,
|
||||||
|
SpaceDragAffectsWorld,
|
||||||
SpaceDragMultiplier,
|
SpaceDragMultiplier,
|
||||||
SpaceDragUnlocked,
|
SpaceDragUnlocked,
|
||||||
SpaceGravityDamping,
|
SpaceGravityDamping,
|
||||||
|
|
@ -345,6 +366,7 @@ enum SettingType {
|
||||||
impl SettingType {
|
impl SettingType {
|
||||||
pub fn change_kind(self) -> ConfigChangeKind {
|
pub fn change_kind(self) -> ConfigChangeKind {
|
||||||
match self {
|
match self {
|
||||||
|
Self::MouseAcceleration | Self::MouseSpeed => ConfigChangeKind::WvrServerConfig,
|
||||||
Self::UseSkybox | Self::UsePassthrough => ConfigChangeKind::EnvironmentBlend,
|
Self::UseSkybox | Self::UsePassthrough => ConfigChangeKind::EnvironmentBlend,
|
||||||
_ => ConfigChangeKind::OverlayConfig,
|
_ => ConfigChangeKind::OverlayConfig,
|
||||||
}
|
}
|
||||||
|
|
@ -369,8 +391,10 @@ impl SettingType {
|
||||||
Self::NotificationsEnabled => &mut config.notifications_enabled,
|
Self::NotificationsEnabled => &mut config.notifications_enabled,
|
||||||
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
|
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
|
||||||
Self::OpaqueBackground => &mut config.opaque_background,
|
Self::OpaqueBackground => &mut config.opaque_background,
|
||||||
|
Self::MouseAcceleration => &mut config.wvr_mouse_acceleration,
|
||||||
Self::ScreenRenderDown => &mut config.screen_render_down,
|
Self::ScreenRenderDown => &mut config.screen_render_down,
|
||||||
Self::SetsOnWatch => &mut config.sets_on_watch,
|
Self::SetsOnWatch => &mut config.sets_on_watch,
|
||||||
|
Self::SpaceDragAffectsWorld => &mut config.space_drag_affects_world,
|
||||||
Self::SpaceDragUnlocked => &mut config.space_drag_unlocked,
|
Self::SpaceDragUnlocked => &mut config.space_drag_unlocked,
|
||||||
Self::SpaceGravityEnabled => &mut config.space_gravity_enabled,
|
Self::SpaceGravityEnabled => &mut config.space_gravity_enabled,
|
||||||
Self::SpaceRotateUnlocked => &mut config.space_rotate_unlocked,
|
Self::SpaceRotateUnlocked => &mut config.space_rotate_unlocked,
|
||||||
|
|
@ -384,11 +408,15 @@ impl SettingType {
|
||||||
|
|
||||||
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
|
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
|
||||||
match self {
|
match self {
|
||||||
|
Self::DefaultCurvature => &mut config.default_curvature,
|
||||||
|
Self::DefaultOpacity => &mut config.default_opacity,
|
||||||
Self::DefaultOverlayScale => &mut config.default_overlay_scale,
|
Self::DefaultOverlayScale => &mut config.default_overlay_scale,
|
||||||
Self::GridOpacity => &mut config.grid_opacity,
|
Self::GridOpacity => &mut config.grid_opacity,
|
||||||
Self::LongPressDuration => &mut config.long_press_duration,
|
Self::LongPressDuration => &mut config.long_press_duration,
|
||||||
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
|
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
|
||||||
|
Self::MouseSpeed => &mut config.wvr_mouse_speed,
|
||||||
Self::ScrollSpeed => &mut config.scroll_speed,
|
Self::ScrollSpeed => &mut config.scroll_speed,
|
||||||
|
Self::SnapAngleDeg => &mut config.snap_angle_deg,
|
||||||
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
|
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
|
||||||
Self::SpaceGravityDamping => &mut config.space_gravity_damping,
|
Self::SpaceGravityDamping => &mut config.space_gravity_damping,
|
||||||
Self::SpaceGravityFlingStrength => &mut config.space_gravity_fling_strength,
|
Self::SpaceGravityFlingStrength => &mut config.space_gravity_fling_strength,
|
||||||
|
|
@ -416,6 +444,13 @@ impl SettingType {
|
||||||
Self::CaptureMethod => {
|
Self::CaptureMethod => {
|
||||||
config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!")
|
config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!")
|
||||||
}
|
}
|
||||||
|
Self::DefaultPositioning => {
|
||||||
|
config.default_positioning =
|
||||||
|
wlx_common::config::DefaultPositioning::from_str(value).expect("Invalid enum value!")
|
||||||
|
}
|
||||||
|
Self::InputCaptureMethod => {
|
||||||
|
config.wvr_input_capture = wlx_common::config::InputCaptureMethod::from_str(value).expect("Invalid enum value!")
|
||||||
|
}
|
||||||
Self::InputEmulationMethod => {
|
Self::InputEmulationMethod => {
|
||||||
config.input_emulation_method =
|
config.input_emulation_method =
|
||||||
wlx_common::config::InputEmulationMethod::from_str(value).expect("Invalid enum value!")
|
wlx_common::config::InputEmulationMethod::from_str(value).expect("Invalid enum value!")
|
||||||
|
|
@ -424,6 +459,9 @@ impl SettingType {
|
||||||
config.keyboard_middle_click_mode =
|
config.keyboard_middle_click_mode =
|
||||||
wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!")
|
wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!")
|
||||||
}
|
}
|
||||||
|
Self::HandsfreeAltTab => {
|
||||||
|
config.handsfree_alt_tab = wlx_common::config::HandsfreeAltTab::from_str(value).expect("Invalid enum value!")
|
||||||
|
}
|
||||||
Self::HandsfreePointer => {
|
Self::HandsfreePointer => {
|
||||||
config.handsfree_pointer = wlx_common::config::HandsfreePointer::from_str(value).expect("Invalid enum value!")
|
config.handsfree_pointer = wlx_common::config::HandsfreePointer::from_str(value).expect("Invalid enum value!")
|
||||||
}
|
}
|
||||||
|
|
@ -437,9 +475,12 @@ impl SettingType {
|
||||||
fn get_enum_title(self, config: &mut GeneralConfig) -> Translation {
|
fn get_enum_title(self, config: &mut GeneralConfig) -> Translation {
|
||||||
match self {
|
match self {
|
||||||
Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method),
|
Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method),
|
||||||
|
Self::DefaultPositioning => Self::get_enum_title_inner(config.default_positioning),
|
||||||
|
Self::InputCaptureMethod => Self::get_enum_title_inner(config.wvr_input_capture),
|
||||||
Self::InputEmulationMethod => Self::get_enum_title_inner(config.input_emulation_method),
|
Self::InputEmulationMethod => Self::get_enum_title_inner(config.input_emulation_method),
|
||||||
Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode),
|
Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode),
|
||||||
Self::HandsfreePointer => Self::get_enum_title_inner(config.handsfree_pointer),
|
Self::HandsfreePointer => Self::get_enum_title_inner(config.handsfree_pointer),
|
||||||
|
Self::HandsfreeAltTab => Self::get_enum_title_inner(config.handsfree_alt_tab),
|
||||||
Self::Language => match &config.language {
|
Self::Language => match &config.language {
|
||||||
Some(lang) => Self::get_enum_title_inner(*lang),
|
Some(lang) => Self::get_enum_title_inner(*lang),
|
||||||
None => Translation::from_translation_key("APP_SETTINGS.OPTION.AUTO"),
|
None => Translation::from_translation_key("APP_SETTINGS.OPTION.AUTO"),
|
||||||
|
|
@ -477,13 +518,18 @@ impl SettingType {
|
||||||
Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"),
|
Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"),
|
||||||
Self::ClickFreezeTimeMs => Ok("APP_SETTINGS.CLICK_FREEZE_TIME_MS"),
|
Self::ClickFreezeTimeMs => Ok("APP_SETTINGS.CLICK_FREEZE_TIME_MS"),
|
||||||
Self::Clock12h => Ok("APP_SETTINGS.CLOCK_12H"),
|
Self::Clock12h => Ok("APP_SETTINGS.CLOCK_12H"),
|
||||||
|
Self::DefaultCurvature => Ok("APP_SETTINGS.DEFAULT_CURVATURE"),
|
||||||
|
Self::DefaultOpacity => Ok("APP_SETTINGS.DEFAULT_OPACITY"),
|
||||||
Self::DefaultOverlayScale => Ok("APP_SETTINGS.DEFAULT_OVERLAY_SCALE"),
|
Self::DefaultOverlayScale => Ok("APP_SETTINGS.DEFAULT_OVERLAY_SCALE"),
|
||||||
|
Self::DefaultPositioning => Ok("APP_SETTINGS.DEFAULT_POSITIONING"),
|
||||||
Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"),
|
Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"),
|
||||||
Self::FocusFollowsMouseMode => Ok("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE"),
|
Self::FocusFollowsMouseMode => Ok("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE"),
|
||||||
Self::GridOpacity => Ok("APP_SETTINGS.GRID_OPACITY"),
|
Self::GridOpacity => Ok("APP_SETTINGS.GRID_OPACITY"),
|
||||||
|
Self::HandsfreeAltTab => Ok("APP_SETTINGS.HANDSFREE_ALT_TAB"),
|
||||||
Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"),
|
Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"),
|
||||||
Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"),
|
Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"),
|
||||||
Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"),
|
Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"),
|
||||||
|
Self::InputCaptureMethod => Ok("APP_SETTINGS.INPUT_CAPTURE_METHOD"),
|
||||||
Self::InputEmulationMethod => Ok("APP_SETTINGS.INPUT_EMULATION_METHOD"),
|
Self::InputEmulationMethod => Ok("APP_SETTINGS.INPUT_EMULATION_METHOD"),
|
||||||
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
|
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
|
||||||
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
|
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
|
||||||
|
|
@ -495,11 +541,15 @@ impl SettingType {
|
||||||
Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"),
|
Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"),
|
||||||
Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"),
|
Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"),
|
||||||
Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"),
|
Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"),
|
||||||
|
Self::MouseSpeed => Ok("APP_SETTINGS.POINTER_SPEED"),
|
||||||
|
Self::MouseAcceleration => Ok("APP_SETTINGS.POINTER_ACCELERATION"),
|
||||||
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
|
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
|
||||||
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
|
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
|
||||||
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
||||||
Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"),
|
Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"),
|
||||||
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
|
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
|
||||||
|
Self::SnapAngleDeg => Ok("APP_SETTINGS.SNAP_ANGLE_DEG"),
|
||||||
|
Self::SpaceDragAffectsWorld => Ok("APP_SETTINGS.SPACE_DRAG_AFFECTS_WORLD"),
|
||||||
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
|
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
|
||||||
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),
|
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),
|
||||||
Self::SpaceGravityDamping => Ok("APP_SETTINGS.SPACE_GRAVITY_DAMPING"),
|
Self::SpaceGravityDamping => Ok("APP_SETTINGS.SPACE_GRAVITY_DAMPING"),
|
||||||
|
|
@ -528,14 +578,21 @@ impl SettingType {
|
||||||
Self::BlockGameInputIgnoreWatch => Some("APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP"),
|
Self::BlockGameInputIgnoreWatch => Some("APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP"),
|
||||||
Self::BlockPosesOnKbdInteraction => Some("APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP"),
|
Self::BlockPosesOnKbdInteraction => Some("APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP"),
|
||||||
Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"),
|
Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"),
|
||||||
|
Self::DefaultCurvature => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"),
|
||||||
|
Self::DefaultOpacity => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"),
|
||||||
Self::DefaultOverlayScale => Some("APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP"),
|
Self::DefaultOverlayScale => Some("APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP"),
|
||||||
|
Self::DefaultPositioning => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"),
|
||||||
Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"),
|
Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"),
|
||||||
Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"),
|
Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"),
|
||||||
|
Self::HandsfreeAltTab => Some("APP_SETTINGS.HANDSFREE_ALT_TAB_HELP"),
|
||||||
Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"),
|
Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"),
|
||||||
|
Self::InputCaptureMethod => Some("APP_SETTINGS.INPUT_CAPTURE_METHOD_HELP"),
|
||||||
Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"),
|
Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"),
|
||||||
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
|
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
|
||||||
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
|
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
|
||||||
|
Self::MouseAcceleration => Some("APP_SETTINGS.POINTER_ACCELERATION_HELP"),
|
||||||
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
|
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
|
||||||
|
Self::SnapAngleDeg => Some("APP_SETTINGS.SNAP_ANGLE_DEG_HELP"),
|
||||||
Self::SpaceGravityDamping => Some("APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP"),
|
Self::SpaceGravityDamping => Some("APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP"),
|
||||||
Self::SpaceGravityFlingStrength => Some("APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH_HELP"),
|
Self::SpaceGravityFlingStrength => Some("APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH_HELP"),
|
||||||
Self::SpaceGravityFloorHeight => Some("APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT_HELP"),
|
Self::SpaceGravityFloorHeight => Some("APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT_HELP"),
|
||||||
|
|
@ -580,8 +637,8 @@ pub fn horiz_cell(layout: &mut Layout, parent: WidgetID) -> anyhow::Result<Widge
|
||||||
WidgetDiv::create(),
|
WidgetDiv::create(),
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
flex_direction: taffy::FlexDirection::Row,
|
flex_direction: taffy::FlexDirection::Row,
|
||||||
align_items: Some(taffy::AlignItems::Center),
|
align_items: Some(taffy::AlignItems::CENTER),
|
||||||
gap: length(8.0),
|
gap: length(8.0_f32),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -597,11 +654,17 @@ fn mount_requires_restart(layout: &mut Layout, parent: WidgetID) -> anyhow::Resu
|
||||||
content,
|
content,
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
wrap: false,
|
wrap: false,
|
||||||
color: Some(drawing::Color::new(1.0, 0.5, 0.5, 1.0)),
|
color: Some(WguiColorName::Danger.into()),
|
||||||
weight: Some(FontWeight::Bold),
|
weight: Some(FontWeight::Bold),
|
||||||
size: Some(10.0),
|
size: Some(10.0),
|
||||||
|
shadow: Some(WguiTextShadow {
|
||||||
|
x: 2.0,
|
||||||
|
y: 2.0,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -633,6 +696,7 @@ impl<T> TabSettings<T> {
|
||||||
config: frontend.interface.general_config(data),
|
config: frontend.interface.general_config(data),
|
||||||
tasks: self.tasks.clone(),
|
tasks: self.tasks.clone(),
|
||||||
idx: 9001,
|
idx: 9001,
|
||||||
|
feats,
|
||||||
};
|
};
|
||||||
|
|
||||||
let settings_mount_params = SettingsMountParams {
|
let settings_mount_params = SettingsMountParams {
|
||||||
|
|
@ -686,7 +750,7 @@ impl<T> TabSettings<T> {
|
||||||
let tasks = Tasks::default();
|
let tasks = Tasks::default();
|
||||||
let tabs = parser_state.fetch_component_as::<ComponentTabs>("tabs")?;
|
let tabs = parser_state.fetch_component_as::<ComponentTabs>("tabs")?;
|
||||||
|
|
||||||
if !frontend.interface.get_feats(data).openxr {
|
if !frontend.interface.get_feats(data).xr_backend.is_open_xr() {
|
||||||
let skybox_btn = tabs.get_tab_button("skybox").unwrap();
|
let skybox_btn = tabs.get_tab_button("skybox").unwrap();
|
||||||
frontend
|
frontend
|
||||||
.layout
|
.layout
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use wgui::{
|
||||||
components::button::ComponentButton, globals::WguiGlobals, layout::WidgetID, parser::Fetchable, task::Tasks,
|
components::button::ComponentButton, globals::WguiGlobals, layout::WidgetID, parser::Fetchable, task::Tasks,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::tab::settings::{horiz_cell, mount_requires_restart};
|
||||||
use crate::util::popup_manager::PopupHolder;
|
use crate::util::popup_manager::PopupHolder;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -56,13 +57,15 @@ fn create_input_profiles_button(
|
||||||
let id = mp.idx.to_string();
|
let id = mp.idx.to_string();
|
||||||
mp.idx += 1;
|
mp.idx += 1;
|
||||||
|
|
||||||
|
let id_cell = horiz_cell(mp.layout, parent)?;
|
||||||
|
|
||||||
let mut params = TemplateParams::new();
|
let mut params = TemplateParams::new();
|
||||||
params.insert("id", &id);
|
params.insert("id", &id);
|
||||||
params.insert("translation", "APP_SETTINGS.INPUT_PROFILES");
|
params.insert("translation", "APP_SETTINGS.INPUT_PROFILES");
|
||||||
params.insert("icon", "dashboard/controller.svg");
|
params.insert("icon", "dashboard/controller.svg");
|
||||||
|
|
||||||
mp.parser_state
|
mp.parser_state
|
||||||
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, parent, params)?;
|
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, id_cell, params)?;
|
||||||
|
|
||||||
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
btn.on_click(Rc::new({
|
btn.on_click(Rc::new({
|
||||||
|
|
@ -73,6 +76,8 @@ fn create_input_profiles_button(
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
mount_requires_restart(mp.layout, id_cell)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,11 +92,12 @@ impl State {
|
||||||
"APP_SETTINGS.CONTROLS",
|
"APP_SETTINGS.CONTROLS",
|
||||||
"dashboard/controller.svg",
|
"dashboard/controller.svg",
|
||||||
)?;
|
)?;
|
||||||
if par.feats.openxr {
|
if par.feats.xr_backend.is_open_xr() {
|
||||||
create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
|
create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
|
||||||
}
|
}
|
||||||
options_dropdown::<wlx_common::config::AltModifier>(par.mp, c, &SettingType::KeyboardMiddleClick)?;
|
options_dropdown::<wlx_common::config::AltModifier>(par.mp, c, &SettingType::KeyboardMiddleClick)?;
|
||||||
options_dropdown::<wlx_common::config::HandsfreePointer>(par.mp, c, &SettingType::HandsfreePointer)?;
|
options_dropdown::<wlx_common::config::HandsfreePointer>(par.mp, c, &SettingType::HandsfreePointer)?;
|
||||||
|
options_dropdown::<wlx_common::config::HandsfreeAltTab>(par.mp, c, &SettingType::HandsfreeAltTab)?;
|
||||||
options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?;
|
options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?;
|
||||||
options_checkbox(par.mp, c, SettingType::LeftHandedMouse)?;
|
options_checkbox(par.mp, c, SettingType::LeftHandedMouse)?;
|
||||||
options_checkbox(par.mp, c, SettingType::AllowSliding)?;
|
options_checkbox(par.mp, c, SettingType::AllowSliding)?;
|
||||||
|
|
@ -99,13 +105,17 @@ impl State {
|
||||||
options_checkbox(par.mp, c, SettingType::InvertScrollDirectionY)?;
|
options_checkbox(par.mp, c, SettingType::InvertScrollDirectionY)?;
|
||||||
options_slider_f32(par.mp, c, SettingType::ScrollSpeed, 0.1, 5.0, 0.1)?;
|
options_slider_f32(par.mp, c, SettingType::ScrollSpeed, 0.1, 5.0, 0.1)?;
|
||||||
options_slider_f32(par.mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1)?;
|
options_slider_f32(par.mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1)?;
|
||||||
|
options_slider_f32(par.mp, c, SettingType::SnapAngleDeg, 0., 45., 5.)?;
|
||||||
|
|
||||||
if par.feats.openxr {
|
if par.feats.xr_backend.is_open_xr() {
|
||||||
options_slider_f32(par.mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1)?;
|
options_slider_f32(par.mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
|
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
|
||||||
|
|
||||||
|
options_slider_f32(par.mp, c, SettingType::MouseSpeed, -1., 1., 0.05)?;
|
||||||
|
options_checkbox(par.mp, c, SettingType::MouseAcceleration)?;
|
||||||
|
|
||||||
Ok(State {
|
Ok(State {
|
||||||
popup_input_profiles: popup,
|
popup_input_profiles: popup,
|
||||||
frontend_tasks: par.frontend_tasks.clone(),
|
frontend_tasks: par.frontend_tasks.clone(),
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,14 @@ impl SettingsTab for State {
|
||||||
for task in self.tasks.drain() {
|
for task in self.tasks.drain() {
|
||||||
match task {
|
match task {
|
||||||
Task::WhisperDownloadClosed => {
|
Task::WhisperDownloadClosed => {
|
||||||
if let Some(model) = self.pending_download.take() {
|
if let Some(model) = self.pending_download.take()
|
||||||
if !whisper_model_path(model.file_name).exists() {
|
&& !whisper_model_path(model.file_name).exists()
|
||||||
// download failed, set to selection to none
|
{
|
||||||
par.general_config.whisper_model = "".into();
|
// download failed, set to selection to none
|
||||||
par.config_change_kind.replace(ConfigChangeKind::Other);
|
par.general_config.whisper_model = "".into();
|
||||||
// reload the tab
|
par.config_change_kind.replace(ConfigChangeKind::Other);
|
||||||
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
|
// reload the tab
|
||||||
}
|
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task::WhisperRemoveUnused => {
|
Task::WhisperRemoveUnused => {
|
||||||
|
|
@ -152,7 +152,7 @@ impl State {
|
||||||
options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?;
|
options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?;
|
||||||
options_checkbox(par.mp, c, SettingType::NotificationsSoundEnabled)?;
|
options_checkbox(par.mp, c, SettingType::NotificationsSoundEnabled)?;
|
||||||
options_checkbox(par.mp, c, SettingType::KeyboardSoundEnabled)?;
|
options_checkbox(par.mp, c, SettingType::KeyboardSoundEnabled)?;
|
||||||
if !par.feats.openxr || par.feats.monado {
|
if par.feats.xr_backend.is_open_vr() || par.feats.monado {
|
||||||
// monado or openvr
|
// monado or openvr
|
||||||
options_checkbox(par.mp, c, SettingType::BlockGameInput)?;
|
options_checkbox(par.mp, c, SettingType::BlockGameInput)?;
|
||||||
options_checkbox(par.mp, c, SettingType::BlockGameInputIgnoreWatch)?;
|
options_checkbox(par.mp, c, SettingType::BlockGameInputIgnoreWatch)?;
|
||||||
|
|
@ -303,8 +303,8 @@ fn whisper_models_dropdown(mp: &mut MacroParams, parent: WidgetID) -> anyhow::Re
|
||||||
|
|
||||||
let mut params = TemplateParams::new();
|
let mut params = TemplateParams::new();
|
||||||
params.insert("id", &id);
|
params.insert("id", &id);
|
||||||
params.insert("translation", "APP_SETTINGS.WHISPER_MODEL".into());
|
params.insert("translation", "APP_SETTINGS.WHISPER_MODEL");
|
||||||
params.insert("tooltip", "APP_SETTINGS.WHISPER_MODEL_HELP".into());
|
params.insert("tooltip", "APP_SETTINGS.WHISPER_MODEL_HELP");
|
||||||
|
|
||||||
mp.parser_state
|
mp.parser_state
|
||||||
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
|
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,120 @@
|
||||||
use crate::tab::settings::{
|
use std::rc::Rc;
|
||||||
SettingType, SettingsMountParams, SettingsTab,
|
|
||||||
macros::{options_category, options_checkbox, options_dropdown, options_slider_f32},
|
use wgui::{
|
||||||
|
components::button::ComponentButton,
|
||||||
|
globals::WguiGlobals,
|
||||||
|
layout::WidgetID,
|
||||||
|
parser::{Fetchable, TemplateParams},
|
||||||
|
task::Tasks,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct State {}
|
use crate::{
|
||||||
|
frontend::FrontendTasks,
|
||||||
|
tab::settings::{
|
||||||
|
SettingType, SettingsMountParams, SettingsTab, horiz_cell,
|
||||||
|
macros::{options_category, options_checkbox, options_dropdown, options_slider_f32},
|
||||||
|
mount_requires_restart,
|
||||||
|
},
|
||||||
|
util::popup_manager::PopupHolder,
|
||||||
|
views::{ViewUpdateParams, color_palettes},
|
||||||
|
};
|
||||||
|
|
||||||
impl SettingsTab for State {}
|
#[derive(Clone)]
|
||||||
|
enum Task {
|
||||||
|
OpenColorPalettes,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
popup_color_palettes: PopupHolder<color_palettes::View>,
|
||||||
|
frontend_tasks: FrontendTasks,
|
||||||
|
globals: WguiGlobals,
|
||||||
|
tasks: Tasks<Task>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SettingsTab for State {
|
||||||
|
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||||
|
self.popup_color_palettes.update(par)?;
|
||||||
|
|
||||||
|
for task in self.tasks.drain() {
|
||||||
|
match task {
|
||||||
|
Task::OpenColorPalettes => {
|
||||||
|
color_palettes::mount_popup(
|
||||||
|
self.frontend_tasks.clone(),
|
||||||
|
self.globals.clone(),
|
||||||
|
self.popup_color_palettes.clone(),
|
||||||
|
par.general_config.color_palette.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
||||||
|
let tasks = Tasks::<Task>::new();
|
||||||
|
let popup = PopupHolder::<color_palettes::View>::default();
|
||||||
|
|
||||||
let c = options_category(
|
let c = options_category(
|
||||||
par.mp,
|
par.mp,
|
||||||
par.id_parent,
|
par.id_parent,
|
||||||
"APP_SETTINGS.LOOK_AND_FEEL",
|
"APP_SETTINGS.LOOK_AND_FEEL",
|
||||||
"dashboard/palette.svg",
|
"dashboard/palette.svg",
|
||||||
)?;
|
)?;
|
||||||
|
create_color_palettes_button(par.mp, c, tasks.clone(), &popup)?;
|
||||||
options_dropdown::<wlx_common::locale::Language>(par.mp, c, &SettingType::Language)?;
|
options_dropdown::<wlx_common::locale::Language>(par.mp, c, &SettingType::Language)?;
|
||||||
options_checkbox(par.mp, c, SettingType::OpaqueBackground)?;
|
options_checkbox(par.mp, c, SettingType::OpaqueBackground)?;
|
||||||
options_checkbox(par.mp, c, SettingType::HideUsername)?;
|
options_checkbox(par.mp, c, SettingType::HideUsername)?;
|
||||||
options_checkbox(par.mp, c, SettingType::HideGrabHelp)?;
|
options_checkbox(par.mp, c, SettingType::HideGrabHelp)?;
|
||||||
|
options_slider_f32(par.mp, c, SettingType::DefaultCurvature, 0.0, 0.5, 0.05)?; // min, max, step
|
||||||
|
options_slider_f32(par.mp, c, SettingType::DefaultOpacity, 0.05, 1.0, 0.05)?; // min, max, step
|
||||||
options_slider_f32(par.mp, c, SettingType::DefaultOverlayScale, 0.7, 1.5, 0.05)?; // min, max, step
|
options_slider_f32(par.mp, c, SettingType::DefaultOverlayScale, 0.7, 1.5, 0.05)?; // min, max, step
|
||||||
|
options_dropdown::<wlx_common::config::DefaultPositioning>(par.mp, c, &SettingType::DefaultPositioning)?;
|
||||||
options_slider_f32(par.mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1)?; // min, max, step
|
options_slider_f32(par.mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1)?; // min, max, step
|
||||||
options_slider_f32(par.mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05)?; // min, max, step
|
options_slider_f32(par.mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05)?; // min, max, step
|
||||||
options_slider_f32(par.mp, c, SettingType::UiRoundMultiplier, 0.1, 5.0, 0.1)?;
|
options_slider_f32(par.mp, c, SettingType::UiRoundMultiplier, 0.1, 5.0, 0.1)?;
|
||||||
options_checkbox(par.mp, c, SettingType::EnableWatch)?;
|
options_checkbox(par.mp, c, SettingType::EnableWatch)?;
|
||||||
options_checkbox(par.mp, c, SettingType::SetsOnWatch)?;
|
options_checkbox(par.mp, c, SettingType::SetsOnWatch)?;
|
||||||
options_checkbox(par.mp, c, SettingType::Clock12h)?;
|
options_checkbox(par.mp, c, SettingType::Clock12h)?;
|
||||||
Ok(State {})
|
Ok(State {
|
||||||
|
popup_color_palettes: popup,
|
||||||
|
frontend_tasks: par.frontend_tasks.clone(),
|
||||||
|
globals: par.mp.doc_params.globals.clone(),
|
||||||
|
tasks,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_color_palettes_button(
|
||||||
|
mp: &mut crate::tab::settings::macros::MacroParams,
|
||||||
|
parent: WidgetID,
|
||||||
|
tasks: Tasks<Task>,
|
||||||
|
_popup: &PopupHolder<color_palettes::View>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let id = mp.idx.to_string();
|
||||||
|
mp.idx += 1;
|
||||||
|
|
||||||
|
let id_cell = horiz_cell(mp.layout, parent)?;
|
||||||
|
|
||||||
|
let mut params = TemplateParams::new();
|
||||||
|
params.insert("id", &id);
|
||||||
|
params.insert("translation", "APP_SETTINGS.COLOR_PALETTE");
|
||||||
|
params.insert("icon", "dashboard/palette.svg");
|
||||||
|
|
||||||
|
mp.parser_state
|
||||||
|
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, id_cell, params)?;
|
||||||
|
|
||||||
|
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
let tasks = tasks.clone();
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks.push(Task::OpenColorPalettes);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
mount_requires_restart(mp.layout, id_cell)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ impl State {
|
||||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
||||||
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?;
|
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?;
|
||||||
options_dropdown::<wlx_common::config::InputEmulationMethod>(par.mp, c, &SettingType::InputEmulationMethod)?;
|
options_dropdown::<wlx_common::config::InputEmulationMethod>(par.mp, c, &SettingType::InputEmulationMethod)?;
|
||||||
|
options_dropdown::<wlx_common::config::InputCaptureMethod>(par.mp, c, &SettingType::InputCaptureMethod)?;
|
||||||
options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?;
|
options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?;
|
||||||
options_checkbox(par.mp, c, SettingType::XwaylandByDefault)?;
|
options_checkbox(par.mp, c, SettingType::XwaylandByDefault)?;
|
||||||
options_checkbox(par.mp, c, SettingType::UprightScreenFix)?;
|
options_checkbox(par.mp, c, SettingType::UprightScreenFix)?;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use wgui::{
|
||||||
use crate::{
|
use crate::{
|
||||||
tab::settings::{
|
tab::settings::{
|
||||||
SettingType, SettingsMountParams, SettingsTab,
|
SettingType, SettingsMountParams, SettingsTab,
|
||||||
macros::{options_category, options_checkbox, options_slider_f32},
|
macros::{options_button, options_category, options_checkbox, options_slider_f32},
|
||||||
},
|
},
|
||||||
util::wgui_simple,
|
util::wgui_simple,
|
||||||
};
|
};
|
||||||
|
|
@ -54,10 +54,37 @@ impl State {
|
||||||
let id_gravity_enabled_parent = tab_state.get_widget_id("gravity_enabled_parent")?;
|
let id_gravity_enabled_parent = tab_state.get_widget_id("gravity_enabled_parent")?;
|
||||||
let id_space_gravity_parent = tab_state.get_widget_id("space_gravity_parent")?;
|
let id_space_gravity_parent = tab_state.get_widget_id("space_gravity_parent")?;
|
||||||
|
|
||||||
if !par.feats.openxr || par.feats.monado {
|
if par.feats.xr_backend.is_open_vr() || par.feats.monado {
|
||||||
// monado or openvr
|
// monado or openvr
|
||||||
|
|
||||||
|
options_button(
|
||||||
|
par.mp,
|
||||||
|
c,
|
||||||
|
"APP_SETTINGS.RESET_PLAYSPACE",
|
||||||
|
"dashboard/refresh.svg",
|
||||||
|
super::Task::ResetPlayspace,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
options_button(
|
||||||
|
par.mp,
|
||||||
|
c,
|
||||||
|
"APP_SETTINGS.SAVE_PLAYSPACE_CENTER",
|
||||||
|
"dashboard/recenter.svg",
|
||||||
|
super::Task::SavePlayspaceCenter,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
options_button(
|
||||||
|
par.mp,
|
||||||
|
c,
|
||||||
|
"APP_SETTINGS.RESET_PLAYSPACE_CENTER",
|
||||||
|
"dashboard/trash.svg",
|
||||||
|
super::Task::ResetPlayspaceCenter,
|
||||||
|
)?;
|
||||||
|
|
||||||
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragUnlocked)?;
|
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragUnlocked)?;
|
||||||
|
|
||||||
|
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragAffectsWorld)?;
|
||||||
|
|
||||||
options_slider_f32(
|
options_slider_f32(
|
||||||
par.mp,
|
par.mp,
|
||||||
id_common_options_parent,
|
id_common_options_parent,
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,6 @@ impl State {
|
||||||
"APP_SETTINGS.TROUBLESHOOTING",
|
"APP_SETTINGS.TROUBLESHOOTING",
|
||||||
"dashboard/cpu.svg",
|
"dashboard/cpu.svg",
|
||||||
)?;
|
)?;
|
||||||
options_danger_button(
|
|
||||||
par.mp,
|
|
||||||
c,
|
|
||||||
"APP_SETTINGS.RESET_PLAYSPACE",
|
|
||||||
"dashboard/recenter.svg",
|
|
||||||
Task::ResetPlayspace,
|
|
||||||
)?;
|
|
||||||
options_danger_button(
|
options_danger_button(
|
||||||
par.mp,
|
par.mp,
|
||||||
c,
|
c,
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,14 @@ impl<T> TabWelcome<T> {
|
||||||
for i in 0..PAGE_COUNT {
|
for i in 0..PAGE_COUNT {
|
||||||
let mut params = TemplateParams::new();
|
let mut params = TemplateParams::new();
|
||||||
let is_selected = i == self.current_page;
|
let is_selected = i == self.current_page;
|
||||||
params.insert("COLOR", if is_selected { "#FFFFFF" } else { "#FFFFFF11" });
|
params.insert(
|
||||||
|
"COLOR",
|
||||||
|
if is_selected {
|
||||||
|
"primary"
|
||||||
|
} else {
|
||||||
|
"on_background(opacity-0.25)"
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self
|
self
|
||||||
.state
|
.state
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::assets::Asset;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lang_json_files_are_valid() {
|
||||||
|
for file in Asset::iter() {
|
||||||
|
if file.ends_with(".json") {
|
||||||
|
let data = Asset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
|
||||||
|
let text =
|
||||||
|
String::from_utf8(data.data.to_vec()).unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
|
||||||
|
serde_json::from_str::<serde_json::Value>(&text)
|
||||||
|
.unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_csv_keys(data: &[u8]) -> Vec<String> {
|
||||||
|
let text = std::str::from_utf8(data).expect("en.csv is not valid UTF-8");
|
||||||
|
let mut keys = Vec::new();
|
||||||
|
let mut chars = text.chars().peekable();
|
||||||
|
while chars.peek().is_some() {
|
||||||
|
let key = read_csv_field(&mut chars);
|
||||||
|
// skip comma separator
|
||||||
|
if chars.peek() == Some(&',') {
|
||||||
|
chars.next();
|
||||||
|
}
|
||||||
|
// skip value field
|
||||||
|
read_csv_field(&mut chars);
|
||||||
|
// skip comma separator
|
||||||
|
if chars.peek() == Some(&',') {
|
||||||
|
chars.next();
|
||||||
|
}
|
||||||
|
// skip description field (may contain newlines via quotes)
|
||||||
|
read_csv_field(&mut chars);
|
||||||
|
// skip newline
|
||||||
|
if chars.peek() == Some(&'\n') {
|
||||||
|
chars.next();
|
||||||
|
}
|
||||||
|
keys.push(key);
|
||||||
|
}
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_csv_field(chars: &mut std::iter::Peekable<std::str::Chars>) -> String {
|
||||||
|
let mut field = String::new();
|
||||||
|
if chars.peek() == Some(&'"') {
|
||||||
|
// quoted field
|
||||||
|
chars.next(); // consume opening quote
|
||||||
|
loop {
|
||||||
|
match chars.next() {
|
||||||
|
Some('"') => {
|
||||||
|
if chars.peek() == Some(&'"') {
|
||||||
|
field.push('"'); // escaped quote
|
||||||
|
chars.next();
|
||||||
|
} else {
|
||||||
|
break; // closing quote
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(c) => field.push(c),
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// unquoted field
|
||||||
|
for c in chars.by_ref() {
|
||||||
|
if c == ',' || c == '\n' {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
field.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_nested<'a>(value: &'a serde_json::Value, key: &str) -> Option<&'a serde_json::Value> {
|
||||||
|
let mut current = value;
|
||||||
|
for segment in key.split('.') {
|
||||||
|
current = current.get(segment)?;
|
||||||
|
}
|
||||||
|
Some(current)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lang_json_files_contain_all_keys() {
|
||||||
|
let en_data = Asset::get("lang/en.csv").expect("en.csv not found");
|
||||||
|
let expected_keys = parse_csv_keys(&en_data.data);
|
||||||
|
|
||||||
|
for file in Asset::iter() {
|
||||||
|
if !file.ends_with(".json") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let data = Asset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
|
||||||
|
let text =
|
||||||
|
String::from_utf8(data.data.to_vec()).unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
|
||||||
|
let json: serde_json::Value =
|
||||||
|
serde_json::from_str(&text).unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
|
||||||
|
|
||||||
|
for key in &expected_keys {
|
||||||
|
assert!(get_nested(&json, key).is_some(), "missing key {key} in {file}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,113 @@
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use crate::util::{networking::http_client, steam_utils::AppID};
|
use crate::util::{networking::http_client, steam_utils::AppID};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use wlx_common::{async_executor::AsyncExecutor, cache_dir};
|
use strum::AsRefStr;
|
||||||
|
use wlx_common::cache_dir;
|
||||||
|
|
||||||
|
fn get_unix_timestamp() -> u64 {
|
||||||
|
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, AsRefStr)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum SupporterTier {
|
||||||
|
Platinum,
|
||||||
|
Gold,
|
||||||
|
Silver,
|
||||||
|
Bronze,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SupporterTier {
|
||||||
|
pub fn pretty_str(self) -> String {
|
||||||
|
format!("{self:?} Tier")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn color_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Platinum => "#aaffff",
|
||||||
|
Self::Gold => "#ffffaa",
|
||||||
|
Self::Silver => "#cccccc",
|
||||||
|
Self::Bronze => "#ffaa66",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn tickets(self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Self::Platinum => 20,
|
||||||
|
Self::Gold => 10,
|
||||||
|
Self::Silver => 5,
|
||||||
|
Self::Bronze => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Supporter {
|
||||||
|
pub username: String,
|
||||||
|
pub date: String,
|
||||||
|
pub tier: SupporterTier,
|
||||||
|
pub contribution_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Supporter {
|
||||||
|
pub const fn tickets(&self) -> u32 {
|
||||||
|
self.tier.tickets()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Supporters {
|
||||||
|
pub time_window_days: u32,
|
||||||
|
pub supporters: Vec<Supporter>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct SupportersFile {
|
||||||
|
fetch_timestamp: u64,
|
||||||
|
supporters: Option<Supporters>, // empty in case of server/network failure
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn request_supporters() -> Option<Supporters> {
|
||||||
|
let cache_file_path = "supporters_v1.json";
|
||||||
|
const CACHE_DURATION_SECS: u64 = 7200;
|
||||||
|
let current_timestamp = get_unix_timestamp();
|
||||||
|
|
||||||
|
if let Some(data) = cache_dir::get_data(cache_file_path).await
|
||||||
|
&& let Ok(string) = str::from_utf8(&data)
|
||||||
|
&& let Ok(file) = serde_json::from_str::<SupportersFile>(string)
|
||||||
|
&& file.fetch_timestamp + CACHE_DURATION_SECS > current_timestamp
|
||||||
|
{
|
||||||
|
return file.supporters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform request
|
||||||
|
let mut supporters_file = SupportersFile {
|
||||||
|
fetch_timestamp: current_timestamp,
|
||||||
|
supporters: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = "https://wayvr.org/files/supporters_v1.json";
|
||||||
|
if let Ok(res) = http_client::get_simple(url).await
|
||||||
|
&& let Ok(supporters) = res.into_json::<Supporters>()
|
||||||
|
{
|
||||||
|
supporters_file.supporters = Some(supporters);
|
||||||
|
}
|
||||||
|
|
||||||
|
let json = serde_json::to_string_pretty(&supporters_file).unwrap() /* safe */;
|
||||||
|
|
||||||
|
cache_dir::set_data(cache_file_path, json.as_bytes()).await.ok()?;
|
||||||
|
|
||||||
|
supporters_file.supporters
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CoverArt {
|
pub struct CoverArt {
|
||||||
// can be empty in case if data couldn't be fetched (use a fallback image then)
|
// can be empty in case if data couldn't be fetched (use a fallback image then)
|
||||||
pub compressed_image_data: Vec<u8>,
|
pub compressed_image_data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_image(executor: AsyncExecutor, app_id: AppID) -> anyhow::Result<CoverArt> {
|
pub async fn request_cover_art(app_id: AppID) -> anyhow::Result<CoverArt> {
|
||||||
let cache_file_path = format!("cover_arts/{}.bin", app_id);
|
let cache_file_path = format!("cover_arts/{}.bin", app_id);
|
||||||
|
|
||||||
// check if file already exists in cache directory
|
// check if file already exists in cache directory
|
||||||
|
|
@ -23,7 +122,7 @@ pub async fn request_image(executor: AsyncExecutor, app_id: AppID) -> anyhow::Re
|
||||||
app_id
|
app_id
|
||||||
);
|
);
|
||||||
|
|
||||||
match http_client::get_simple(&executor, &url).await {
|
match http_client::get_simple(&url).await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
log::info!("Success");
|
log::info!("Success");
|
||||||
cache_dir::set_data(&cache_file_path, &response.data).await?;
|
cache_dir::set_data(&cache_file_path, &response.data).await?;
|
||||||
|
|
@ -55,11 +154,7 @@ pub struct AppDetailsJSONData {
|
||||||
pub developers: Vec<String>, // ["Valve"]
|
pub developers: Vec<String>, // ["Valve"]
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_app_details_json_internal(
|
async fn get_app_details_json_internal(cache_file_path: &str, app_id: AppID) -> anyhow::Result<AppDetailsJSONData> {
|
||||||
executor: AsyncExecutor,
|
|
||||||
cache_file_path: &str,
|
|
||||||
app_id: AppID,
|
|
||||||
) -> anyhow::Result<AppDetailsJSONData> {
|
|
||||||
// check if file already exists in cache directory
|
// check if file already exists in cache directory
|
||||||
if let Some(data) = cache_dir::get_data(cache_file_path).await {
|
if let Some(data) = cache_dir::get_data(cache_file_path).await {
|
||||||
return Ok(serde_json::from_value(serde_json::from_slice(&data)?)?);
|
return Ok(serde_json::from_value(serde_json::from_slice(&data)?)?);
|
||||||
|
|
@ -68,7 +163,7 @@ async fn get_app_details_json_internal(
|
||||||
// Fetch from Steam API
|
// Fetch from Steam API
|
||||||
log::info!("Fetching app detail ID {}", app_id);
|
log::info!("Fetching app detail ID {}", app_id);
|
||||||
let url = format!("https://store.steampowered.com/api/appdetails?appids={}", app_id);
|
let url = format!("https://store.steampowered.com/api/appdetails?appids={}", app_id);
|
||||||
let response = http_client::get_simple(&executor, &url).await?;
|
let response = http_client::get_simple(&url).await?;
|
||||||
let res_utf8 = String::from_utf8(response.data)?;
|
let res_utf8 = String::from_utf8(response.data)?;
|
||||||
let root = serde_json::from_str::<serde_json::Value>(&res_utf8)?;
|
let root = serde_json::from_str::<serde_json::Value>(&res_utf8)?;
|
||||||
let body = root.get(&app_id).context("invalid body")?;
|
let body = root.get(&app_id).context("invalid body")?;
|
||||||
|
|
@ -88,10 +183,10 @@ async fn get_app_details_json_internal(
|
||||||
Ok(app_details)
|
Ok(app_details)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_app_details_json(executor: AsyncExecutor, app_id: AppID) -> Option<AppDetailsJSONData> {
|
pub async fn get_app_details_json(app_id: AppID) -> Option<AppDetailsJSONData> {
|
||||||
let cache_file_path = format!("app_details/{}.json", app_id);
|
let cache_file_path = format!("app_details/{}.json", app_id);
|
||||||
|
|
||||||
match get_app_details_json_internal(executor, &cache_file_path, app_id).await {
|
match get_app_details_json_internal(&cache_file_path, app_id).await {
|
||||||
Ok(r) => Some(r),
|
Ok(r) => Some(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to get app details: {:?}", e);
|
log::error!("Failed to get app details: {:?}", e);
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,11 @@
|
||||||
//
|
|
||||||
// example smol+hyper usage derived from
|
|
||||||
// https://github.com/smol-rs/smol/blob/master/examples/hyper-client.rs
|
|
||||||
// under Apache-2.0 + MIT license.
|
|
||||||
// Repository URL: https://github.com/smol-rs/smol
|
|
||||||
//
|
|
||||||
|
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use async_native_tls::TlsStream;
|
use smol::{channel::bounded, io::AsyncWriteExt as _};
|
||||||
use http_body_util::{BodyStream, Empty};
|
use std::{io::Read as _, path::Path, str, sync::OnceLock};
|
||||||
use hyper::Request;
|
|
||||||
use smol::{net::TcpStream, prelude::*};
|
const IO_BUFFER_SIZE: usize = 256 * 1024;
|
||||||
use std::convert::TryInto;
|
const CHANNEL_CAPACITY: usize = 8;
|
||||||
use std::pin::Pin;
|
const MAX_INITIAL_ALLOCATION: usize = 8 * 1024 * 1024;
|
||||||
use std::task::{Context, Poll};
|
|
||||||
use wlx_common::async_executor::AsyncExecutor;
|
|
||||||
pub struct HttpClientResponse {
|
pub struct HttpClientResponse {
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
@ -21,276 +13,252 @@ pub struct HttpClientResponse {
|
||||||
impl HttpClientResponse {
|
impl HttpClientResponse {
|
||||||
pub fn into_json<T>(self) -> anyhow::Result<T>
|
pub fn into_json<T>(self) -> anyhow::Result<T>
|
||||||
where
|
where
|
||||||
T: for<'a> serde::Deserialize<'a>,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
let utf8 = str::from_utf8(&self.data)?;
|
let utf8 = str::from_utf8(&self.data)?;
|
||||||
Ok(serde_json::from_str::<T>(utf8)?)
|
Ok(serde_json::from_str(utf8)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct ProgressFuncData {
|
pub struct ProgressFuncData {
|
||||||
pub bytes_downloaded: u64,
|
pub bytes_downloaded: u64,
|
||||||
pub file_size: u64,
|
pub file_size: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ProgressFunc = Box<dyn Fn(ProgressFuncData)>;
|
pub type ProgressFunc<'a> = Box<dyn FnMut(ProgressFuncData) + 'a>;
|
||||||
|
|
||||||
pub struct GetParams<'a> {
|
pub struct GetParams<'a> {
|
||||||
pub executor: &'a AsyncExecutor,
|
|
||||||
pub url: &'a str,
|
pub url: &'a str,
|
||||||
pub on_progress: Option<ProgressFunc>,
|
pub on_progress: Option<ProgressFunc<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get(params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> {
|
enum HttpClientData {
|
||||||
let url: hyper::Uri = params.url.try_into()?;
|
FileSize(u64),
|
||||||
let req = Request::builder()
|
Chunk(Vec<u8>),
|
||||||
.header(
|
Ended(anyhow::Result<()>),
|
||||||
hyper::header::HOST,
|
|
||||||
url.authority().context("invalid authority")?.clone().as_str(),
|
|
||||||
)
|
|
||||||
.uri(url)
|
|
||||||
.body(Empty::new())?;
|
|
||||||
|
|
||||||
let resp = fetch_and_follow_redirects(params.executor, req, params.on_progress, ¶ms.url).await?;
|
|
||||||
|
|
||||||
Ok(resp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_and_follow_redirects(
|
struct DownloadStream {
|
||||||
executor: &AsyncExecutor,
|
file_size: u64,
|
||||||
req: hyper::Request<Empty<&'static [u8]>>,
|
receiver: smol::channel::Receiver<HttpClientData>,
|
||||||
mut on_progress: Option<ProgressFunc>,
|
}
|
||||||
initial_url: &str,
|
|
||||||
) -> anyhow::Result<HttpClientResponse> {
|
|
||||||
log::info!("fetching URL \"{}\"", initial_url);
|
|
||||||
|
|
||||||
let resp = fetch(executor, req.clone()).await?;
|
static HTTP_AGENT: OnceLock<ureq::Agent> = OnceLock::new();
|
||||||
let status = resp.status();
|
|
||||||
|
|
||||||
if status.is_redirection() {
|
fn http_agent() -> &'static ureq::Agent {
|
||||||
let next_req = follow_single_redirect(&req, &resp).await?;
|
HTTP_AGENT.get_or_init(|| {
|
||||||
|
ureq::Agent::config_builder()
|
||||||
|
.max_redirects(10)
|
||||||
|
.http_status_as_error(false)
|
||||||
|
.build()
|
||||||
|
.new_agent()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let max_redirects = 10;
|
fn thread_http_client(
|
||||||
let mut current_req = next_req;
|
url: &str,
|
||||||
let mut redirects = 0;
|
allow_missing_content_length: bool,
|
||||||
loop {
|
sender: smol::channel::Sender<HttpClientData>,
|
||||||
let resp = fetch(executor, current_req.clone()).await?;
|
) -> anyhow::Result<()> {
|
||||||
let resp_status = resp.status();
|
log::info!("fetching URL \"{}\"", url);
|
||||||
|
let agent = http_agent().clone();
|
||||||
|
|
||||||
if resp_status.is_success() {
|
let response = agent
|
||||||
let (parts, body) = resp.into_parts();
|
.get(url)
|
||||||
|
.header("Accept-Encoding", "identity")
|
||||||
|
.call()
|
||||||
|
.with_context(|| format!("failed to fetch URL \"{url}\""))?;
|
||||||
|
|
||||||
let mut bytes_downloaded: u64 = 0;
|
if !response.status().is_success() {
|
||||||
let mut file_size: u64 = 1;
|
anyhow::bail!("non-200 HTTP response: {}", response.status().as_u16(),);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(val) = parts.headers.get("Content-Length")
|
let file_size = match response.body().content_length() {
|
||||||
&& let Ok(str) = val.to_str()
|
Some(file_size) => file_size,
|
||||||
&& let Ok(s) = str.parse()
|
|
||||||
{
|
None if allow_missing_content_length => 0,
|
||||||
file_size = s;
|
|
||||||
|
None => {
|
||||||
|
anyhow::bail!("HTTP response has no Content-Length header");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sender.send_blocking(HttpClientData::FileSize(file_size))?;
|
||||||
|
|
||||||
|
let mut reader = response.into_body().into_reader();
|
||||||
|
let mut buffer = [0_u8; IO_BUFFER_SIZE];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let count = reader.read(&mut buffer).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed while reading HTTP response body \
|
||||||
|
from \"{url}\""
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.send_blocking(HttpClientData::Chunk(buffer[..count].to_vec()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a HTTP request in a separate thread and streams its body through an async channel
|
||||||
|
/// The request, TLS operations, and all BodyReader reads remain inside one
|
||||||
|
/// blocking worker. Only owned byte chunks cross back to the async task.
|
||||||
|
async fn start_download(url: &str, allow_missing_content_length: bool) -> anyhow::Result<DownloadStream> {
|
||||||
|
let url = url.to_owned();
|
||||||
|
|
||||||
|
let (sender, receiver) = bounded::<HttpClientData>(CHANNEL_CAPACITY);
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let res = thread_http_client(&url, allow_missing_content_length, sender.clone());
|
||||||
|
let _ = sender.send_blocking(HttpClientData::Ended(res));
|
||||||
|
log::debug!("thread_http_client exiting");
|
||||||
|
});
|
||||||
|
|
||||||
|
let file_size = match receiver.recv().await? {
|
||||||
|
HttpClientData::Ended(res) => match res {
|
||||||
|
Ok(_) => anyhow::bail!("HTTP worker failure"),
|
||||||
|
Err(e) => return Err(anyhow::anyhow!(e)),
|
||||||
|
},
|
||||||
|
HttpClientData::FileSize(file_size) => file_size,
|
||||||
|
_ => {
|
||||||
|
anyhow::bail!("HTTP worker failure")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(DownloadStream { file_size, receiver })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Downloads a response into memory.
|
||||||
|
///
|
||||||
|
/// This fails if the server does not provide a Content-Length header.
|
||||||
|
pub async fn get(mut params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> {
|
||||||
|
let DownloadStream { file_size, receiver } = start_download(params.url, false).await?;
|
||||||
|
|
||||||
|
let initial_capacity = usize::try_from(file_size).unwrap_or(0).min(MAX_INITIAL_ALLOCATION);
|
||||||
|
|
||||||
|
let mut data = Vec::with_capacity(initial_capacity);
|
||||||
|
let mut bytes_downloaded = 0_u64;
|
||||||
|
|
||||||
|
while let Ok(msg) = receiver.recv().await {
|
||||||
|
match msg {
|
||||||
|
HttpClientData::FileSize(_) => unreachable!(),
|
||||||
|
HttpClientData::Ended(e) => {
|
||||||
|
if let Err(e) = e {
|
||||||
|
anyhow::bail!("HTTP request failed: {}", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
HttpClientData::Chunk(chunk) => {
|
||||||
|
bytes_downloaded += chunk.len() as u64;
|
||||||
|
data.extend_from_slice(&chunk);
|
||||||
|
|
||||||
let data = BodyStream::new(body)
|
if let Some(on_progress) = params.on_progress.as_mut() {
|
||||||
.try_fold(Vec::new(), |mut body, chunk| {
|
on_progress(ProgressFuncData {
|
||||||
if let Some(chunk) = chunk.data_ref() {
|
bytes_downloaded,
|
||||||
bytes_downloaded += chunk.len() as u64;
|
file_size,
|
||||||
body.extend_from_slice(chunk);
|
});
|
||||||
|
|
||||||
if let Some(on_progress) = &mut on_progress {
|
|
||||||
on_progress(ProgressFuncData {
|
|
||||||
bytes_downloaded,
|
|
||||||
file_size,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(body)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
return Ok(HttpClientResponse { data });
|
|
||||||
} else if resp_status.is_redirection() {
|
|
||||||
redirects += 1;
|
|
||||||
if redirects >= max_redirects {
|
|
||||||
anyhow::bail!("too many redirects");
|
|
||||||
}
|
}
|
||||||
current_req = follow_single_redirect(¤t_req, &resp).await?;
|
|
||||||
} else {
|
|
||||||
anyhow::bail!("non-200 HTTP response: {}", resp_status.as_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !resp.status().is_success() {
|
if bytes_downloaded != file_size {
|
||||||
// non-200 HTTP response
|
anyhow::bail!(
|
||||||
anyhow::bail!("non-200 HTTP response: {}", resp.status().as_str());
|
"HTTP response size mismatch: expected {} bytes, received {}",
|
||||||
|
file_size,
|
||||||
|
bytes_downloaded,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bytes_downloaded: u64 = 0;
|
|
||||||
let mut file_size: u64 = 1;
|
|
||||||
|
|
||||||
let (parts, body) = resp.into_parts();
|
|
||||||
|
|
||||||
// that's a pretty interesting way to get file size :]
|
|
||||||
if let Some(val) = parts.headers.get("Content-Length")
|
|
||||||
&& let Ok(str) = val.to_str()
|
|
||||||
&& let Ok(s) = str.parse()
|
|
||||||
{
|
|
||||||
file_size = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = BodyStream::new(body)
|
|
||||||
.try_fold(Vec::new(), |mut body, chunk| {
|
|
||||||
if let Some(chunk) = chunk.data_ref() {
|
|
||||||
bytes_downloaded += chunk.len() as u64;
|
|
||||||
body.extend_from_slice(chunk);
|
|
||||||
|
|
||||||
if let Some(on_progress) = &mut on_progress {
|
|
||||||
on_progress(ProgressFuncData {
|
|
||||||
bytes_downloaded,
|
|
||||||
file_size,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(body)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(HttpClientResponse { data })
|
Ok(HttpClientResponse { data })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uri_try_from_str(s: &str) -> anyhow::Result<hyper::http::uri::PathAndQuery> {
|
struct FileCancelGuard {
|
||||||
use std::convert::TryInto;
|
path: std::path::PathBuf,
|
||||||
let uri: hyper::Uri = s.try_into().context("invalid URI")?;
|
should_delete: bool,
|
||||||
uri
|
|
||||||
.path_and_query()
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("URI has no path and query component"))
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn follow_single_redirect(
|
impl Drop for FileCancelGuard {
|
||||||
req: &hyper::Request<Empty<&'static [u8]>>,
|
fn drop(&mut self) {
|
||||||
resp: &hyper::Response<hyper::body::Incoming>,
|
if self.should_delete {
|
||||||
) -> anyhow::Result<hyper::Request<Empty<&'static [u8]>>> {
|
log::warn!("Removing partially downloaded file {:?}", self.path);
|
||||||
let location = resp
|
let _ = std::fs::remove_file(&self.path);
|
||||||
.headers()
|
}
|
||||||
.get(hyper::header::LOCATION)
|
}
|
||||||
.ok_or_else(|| anyhow::anyhow!("redirect response has no Location header"))?;
|
}
|
||||||
|
|
||||||
let location_str = location.to_str().context("invalid redirect location header")?;
|
/// Downloads a response directly to a file.
|
||||||
|
///
|
||||||
|
/// Unlike `get`, this permits responses without a Content-Length header. In
|
||||||
|
/// that case, `ProgressFuncData::file_size` is zero.
|
||||||
|
///
|
||||||
|
/// An existing file is truncated. If the download fails after the file is
|
||||||
|
/// created, a partial file may remain at `path`.
|
||||||
|
pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||||
|
let path = path.as_ref().to_owned();
|
||||||
|
|
||||||
// resolve relative urls against the original url.
|
let DownloadStream { file_size, receiver } = start_download(params.url, true).await?;
|
||||||
let original_uri = req.uri().clone();
|
|
||||||
let next_url: hyper::Uri = if location_str.starts_with("http://") || location_str.starts_with("https://") {
|
let mut file_cancel_guard = FileCancelGuard {
|
||||||
hyper::Uri::try_from(location_str).context("invalid redirect location")?
|
path: path.clone(),
|
||||||
} else {
|
should_delete: true,
|
||||||
let mut parts = original_uri.into_parts();
|
|
||||||
parts.path_and_query = uri_try_from_str(location_str)
|
|
||||||
.context("invalid redirect location")?
|
|
||||||
.into();
|
|
||||||
hyper::Uri::from_parts(parts).context("failed to construct redirect URI")?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
log::info!("redirecting to \"{}\"", next_url);
|
let mut file = smol::fs::File::create(&path)
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("failed to create download file {:?}", path))?;
|
||||||
|
|
||||||
let next_req = Request::builder()
|
let mut bytes_downloaded = 0_u64;
|
||||||
.header(
|
|
||||||
hyper::header::HOST,
|
|
||||||
next_url.authority().context("invalid authority")?.as_str(),
|
|
||||||
)
|
|
||||||
.uri(next_url)
|
|
||||||
.body(Empty::new())?;
|
|
||||||
|
|
||||||
Ok(next_req)
|
while let Ok(msg) = receiver.recv().await {
|
||||||
}
|
match msg {
|
||||||
|
HttpClientData::FileSize(_) => unreachable!(),
|
||||||
pub async fn get_simple(executor: &AsyncExecutor, url: &str) -> anyhow::Result<HttpClientResponse> {
|
HttpClientData::Ended(e) => {
|
||||||
get(GetParams {
|
if let Err(e) = e {
|
||||||
executor,
|
anyhow::bail!("HTTP request failed: {}", e);
|
||||||
url,
|
}
|
||||||
on_progress: None,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch(
|
|
||||||
ex: &AsyncExecutor,
|
|
||||||
req: hyper::Request<http_body_util::Empty<&'static [u8]>>,
|
|
||||||
) -> anyhow::Result<hyper::Response<hyper::body::Incoming>> {
|
|
||||||
let io = {
|
|
||||||
let host = req.uri().host().context("cannot parse host")?;
|
|
||||||
|
|
||||||
match req.uri().scheme_str() {
|
|
||||||
Some("http") => {
|
|
||||||
let stream = {
|
|
||||||
let port = req.uri().port_u16().unwrap_or(80);
|
|
||||||
smol::net::TcpStream::connect((host, port)).await?
|
|
||||||
};
|
|
||||||
SmolStream::Plain(stream)
|
|
||||||
}
|
}
|
||||||
Some("https") => {
|
HttpClientData::Chunk(chunk) => {
|
||||||
// In case of HTTPS, establish a secure TLS connection first.
|
file
|
||||||
let stream = {
|
.write_all(&chunk)
|
||||||
let port = req.uri().port_u16().unwrap_or(443);
|
.await
|
||||||
smol::net::TcpStream::connect((host, port)).await?
|
.with_context(|| format!("failed to write download file {:?}", path,))?;
|
||||||
};
|
|
||||||
let stream = async_native_tls::connect(host, stream).await?;
|
bytes_downloaded += chunk.len() as u64;
|
||||||
SmolStream::Tls(stream)
|
|
||||||
|
if let Some(on_progress) = params.on_progress.as_mut() {
|
||||||
|
on_progress(ProgressFuncData {
|
||||||
|
bytes_downloaded,
|
||||||
|
file_size,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scheme => anyhow::bail!("unsupported scheme: {:?}", scheme),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spawn the HTTP/1 connection.
|
|
||||||
let (mut sender, conn) = hyper::client::conn::http1::handshake(smol_hyper::rt::FuturesIo::new(io)).await?;
|
|
||||||
ex.spawn(async move {
|
|
||||||
if let Err(e) = conn.await {
|
|
||||||
println!("Connection failed: {:?}", e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
// Get the result
|
|
||||||
let result = sender.send_request(req).await?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A TCP or TCP+TLS connection.
|
|
||||||
enum SmolStream {
|
|
||||||
/// A plain TCP connection.
|
|
||||||
Plain(TcpStream),
|
|
||||||
|
|
||||||
/// A TCP connection secured by TLS.
|
|
||||||
Tls(TlsStream<TcpStream>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsyncRead for SmolStream {
|
|
||||||
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<smol::io::Result<usize>> {
|
|
||||||
match &mut *self {
|
|
||||||
SmolStream::Plain(stream) => Pin::new(stream).poll_read(cx, buf),
|
|
||||||
SmolStream::Tls(stream) => Pin::new(stream).poll_read(cx, buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsyncWrite for SmolStream {
|
|
||||||
fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<smol::io::Result<usize>> {
|
|
||||||
match &mut *self {
|
|
||||||
SmolStream::Plain(stream) => Pin::new(stream).poll_write(cx, buf),
|
|
||||||
SmolStream::Tls(stream) => Pin::new(stream).poll_write(cx, buf),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<smol::io::Result<()>> {
|
file
|
||||||
match &mut *self {
|
.flush()
|
||||||
SmolStream::Plain(stream) => Pin::new(stream).poll_close(cx),
|
.await
|
||||||
SmolStream::Tls(stream) => Pin::new(stream).poll_close(cx),
|
.with_context(|| format!("failed to flush download file {:?}", path,))?;
|
||||||
}
|
|
||||||
|
if file_size != 0 && bytes_downloaded != file_size {
|
||||||
|
anyhow::bail!(
|
||||||
|
"HTTP response size mismatch: expected {} bytes, received {}",
|
||||||
|
file_size,
|
||||||
|
bytes_downloaded,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<smol::io::Result<()>> {
|
file_cancel_guard.should_delete = false; // we're good!
|
||||||
match &mut *self {
|
|
||||||
SmolStream::Plain(stream) => Pin::new(stream).poll_flush(cx),
|
Ok(())
|
||||||
SmolStream::Tls(stream) => Pin::new(stream).poll_flush(cx),
|
}
|
||||||
}
|
|
||||||
}
|
pub async fn get_simple(url: &str) -> anyhow::Result<HttpClientResponse> {
|
||||||
|
get(GetParams { url, on_progress: None }).await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use wgui::{globals::WguiGlobals, renderer_vk::text::custom_glyph::CustomGlyphData};
|
use wgui::{globals::WguiGlobals, renderer_vk::text::custom_glyph::CustomGlyphData};
|
||||||
use wlx_common::async_executor::AsyncExecutor;
|
|
||||||
|
|
||||||
use crate::util::networking::http_client;
|
use crate::util::networking::http_client;
|
||||||
|
|
||||||
pub async fn fetch_to_glyph_data(
|
pub async fn fetch_to_glyph_data(globals: &WguiGlobals, url: &str) -> anyhow::Result<(CustomGlyphData, Rc<Vec<u8>>)> {
|
||||||
globals: &WguiGlobals,
|
let res = http_client::get_simple(url).await?;
|
||||||
executor: &AsyncExecutor,
|
|
||||||
url: &str,
|
|
||||||
) -> anyhow::Result<(CustomGlyphData, Rc<Vec<u8>>)> {
|
|
||||||
let res = http_client::get_simple(executor, url).await?;
|
|
||||||
let glyph_data = CustomGlyphData::from_bytes_raster(globals, url, &res.data)?;
|
let glyph_data = CustomGlyphData::from_bytes_raster(globals, url, &res.data)?;
|
||||||
Ok((glyph_data, Rc::new(res.data)))
|
Ok((glyph_data, Rc::new(res.data)))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::util::networking::{self, WAYVR_SKYMAPS_ROOT, http_client};
|
use crate::util::networking::{self, WAYVR_SKYMAPS_ROOT, http_client};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use wlx_common::{async_executor::AsyncExecutor, config_io};
|
use wlx_common::config_io;
|
||||||
pub type SkymapUuid = uuid::Uuid;
|
pub type SkymapUuid = uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
|
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
|
||||||
|
|
@ -160,10 +160,10 @@ impl SkymapCatalog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_catalog(executor: &AsyncExecutor) -> anyhow::Result<SkymapCatalog> {
|
pub async fn request_catalog() -> anyhow::Result<SkymapCatalog> {
|
||||||
log::info!("Fetching skymap list");
|
log::info!("Fetching skymap list");
|
||||||
|
|
||||||
let res = http_client::get_simple(executor, &format!("{}/catalog.json", networking::WAYVR_SKYMAPS_ROOT)).await?;
|
let res = http_client::get_simple(&format!("{}/catalog.json", networking::WAYVR_SKYMAPS_ROOT)).await?;
|
||||||
let catalog = res.into_json::<SkymapCatalog>()?;
|
let catalog = res.into_json::<SkymapCatalog>()?;
|
||||||
catalog.validate()?;
|
catalog.validate()?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,14 +46,7 @@ impl BindingsDropdown for XrInputSubpathKind {
|
||||||
self
|
self
|
||||||
.get_str("Translation")
|
.get_str("Translation")
|
||||||
.map(Translation::from_translation_key)
|
.map(Translation::from_translation_key)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| Translation::from_raw_text(&wlx_common::locale::capitalize_string(self.as_ref())))
|
||||||
let mut chars = self.as_ref().chars();
|
|
||||||
let capitalized = match chars.next() {
|
|
||||||
None => String::new(),
|
|
||||||
Some(first) => first.to_ascii_uppercase().to_string() + chars.as_str(),
|
|
||||||
};
|
|
||||||
Translation::from_raw_text(&capitalized)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn action_str(&self, action: &str, side: XrInputSide) -> Rc<str> {
|
fn action_str(&self, action: &str, side: XrInputSide) -> Rc<str> {
|
||||||
let value = self.as_ref();
|
let value = self.as_ref();
|
||||||
|
|
|
||||||
|
|
@ -285,8 +285,8 @@ impl PopupManager {
|
||||||
let id_content = state.get_widget_id("content")?;
|
let id_content = state.get_widget_id("content")?;
|
||||||
|
|
||||||
let padding = match popup_padding {
|
let padding = match popup_padding {
|
||||||
PopupPadding::Normal => 16.0,
|
PopupPadding::Normal => 16.0_f32,
|
||||||
PopupPadding::None => 0.0,
|
PopupPadding::None => 0.0_f32,
|
||||||
};
|
};
|
||||||
|
|
||||||
layout.tasks.push(LayoutTask::SetWidgetStyle(
|
layout.tasks.push(LayoutTask::SetWidgetStyle(
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ impl SteamUtils {
|
||||||
PathBuf::from(&app_entry.root_path).join(format!("steamapps/appmanifest_{}.acf", app_entry.app_id));
|
PathBuf::from(&app_entry.root_path).join(format!("steamapps/appmanifest_{}.acf", app_entry.app_id));
|
||||||
|
|
||||||
let vdf_data = std::fs::read_to_string(manifest_path)?;
|
let vdf_data = std::fs::read_to_string(manifest_path)?;
|
||||||
let vdf_root = keyvalues_parser::Vdf::parse(&vdf_data)?;
|
let vdf_root = keyvalues_parser::parse(&vdf_data)?.into_vdf();
|
||||||
|
|
||||||
let Some(manifest) = vdf_parse_appstate(app_entry.app_id.clone(), &vdf_root) else {
|
let Some(manifest) = vdf_parse_appstate(app_entry.app_id.clone(), &vdf_root) else {
|
||||||
anyhow::bail!("Failed to parse AppState");
|
anyhow::bail!("Failed to parse AppState");
|
||||||
|
|
@ -262,7 +262,7 @@ impl SteamUtils {
|
||||||
let path = self.get_dir_steamapps().join("libraryfolders.vdf");
|
let path = self.get_dir_steamapps().join("libraryfolders.vdf");
|
||||||
let vdf_data = std::fs::read_to_string(path)?;
|
let vdf_data = std::fs::read_to_string(path)?;
|
||||||
|
|
||||||
let vdf_root = keyvalues_parser::Vdf::parse(&vdf_data)?;
|
let vdf_root = keyvalues_parser::parse(&vdf_data)?.into_vdf();
|
||||||
|
|
||||||
let Some(apps) = vdf_parse_libraryfolders(&vdf_root) else {
|
let Some(apps) = vdf_parse_libraryfolders(&vdf_root) else {
|
||||||
anyhow::bail!("Failed to fetch installed Steam apps");
|
anyhow::bail!("Failed to fetch installed Steam apps");
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
|
||||||
|
|
||||||
use glam::{Mat4, Vec3};
|
use glam::{Mat4, Vec3};
|
||||||
|
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
||||||
use wgui::{
|
use wgui::{
|
||||||
animation::{Animation, AnimationEasing},
|
animation::{Animation, AnimationEasing},
|
||||||
|
color::{WguiColor, WguiColorName},
|
||||||
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
|
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
|
||||||
drawing::Color,
|
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
|
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
|
||||||
renderer_vk::{
|
renderer_vk::{
|
||||||
|
|
@ -66,11 +65,11 @@ impl ToastManager {
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
position: taffy::Position::Absolute,
|
position: taffy::Position::Absolute,
|
||||||
size: taffy::Size {
|
size: taffy::Size {
|
||||||
width: percent(1.0),
|
width: percent(1.0_f32),
|
||||||
height: percent(0.8),
|
height: percent(0.8_f32),
|
||||||
},
|
},
|
||||||
align_items: Some(taffy::AlignItems::End),
|
align_items: Some(taffy::AlignItems::END),
|
||||||
justify_content: Some(taffy::JustifyContent::Center),
|
justify_content: Some(taffy::JustifyContent::CENTER),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -78,23 +77,23 @@ impl ToastManager {
|
||||||
let (rect, _) = layout.add_child(
|
let (rect, _) = layout.add_child(
|
||||||
root.id,
|
root.id,
|
||||||
WidgetRectangle::create(WidgetRectangleParams {
|
WidgetRectangle::create(WidgetRectangleParams {
|
||||||
color: TOOLTIP_COLOR,
|
color: TOOLTIP_COLOR.into(),
|
||||||
border_color: TOOLTIP_BORDER_COLOR,
|
border_color: TOOLTIP_BORDER_COLOR.into(),
|
||||||
border: 2.0,
|
border: 2.0,
|
||||||
round: WLength::Percent(1.0),
|
round: WLength::Percent(1.0),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
position: taffy::Position::Relative,
|
position: taffy::Position::Relative,
|
||||||
gap: length(4.0),
|
gap: length(4.0_f32),
|
||||||
padding: taffy::Rect {
|
padding: taffy::Rect {
|
||||||
left: length(16.0),
|
left: length(16.0_f32),
|
||||||
right: length(16.0),
|
right: length(16.0_f32),
|
||||||
top: length(8.0),
|
top: length(8.0_f32),
|
||||||
bottom: length(8.0),
|
bottom: length(8.0_f32),
|
||||||
},
|
},
|
||||||
max_size: taffy::Size {
|
max_size: taffy::Size {
|
||||||
width: length(400.0),
|
width: length(400.0_f32),
|
||||||
height: auto(),
|
height: auto(),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -111,6 +110,7 @@ impl ToastManager {
|
||||||
wrap: true,
|
wrap: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let (label, _) = layout.add_child(rect.id, label, taffy::Style { ..Default::default() })?;
|
let (label, _) = layout.add_child(rect.id, label, taffy::Style { ..Default::default() })?;
|
||||||
|
|
@ -132,11 +132,15 @@ impl ToastManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||||
rect.params.color.a = opacity;
|
rect.params.color = rect.params.color.with_alpha(opacity);
|
||||||
rect.params.border_color.a = opacity;
|
rect.params.border_color = rect.params.border_color.with_alpha(opacity);
|
||||||
|
|
||||||
let mut label = common.state.widgets.get_as::<WidgetLabel>(label.id).unwrap();
|
let mut label = common.state.widgets.get_as::<WidgetLabel>(label.id).unwrap();
|
||||||
label.set_color(common, Color::new(1.0, 1.0, 1.0, opacity), true);
|
label.set_color(
|
||||||
|
common,
|
||||||
|
WguiColor::from(WguiColorName::OnBackgroundVariant).with_alpha(opacity),
|
||||||
|
true,
|
||||||
|
);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use glam::{Mat4, Vec2};
|
||||||
use wgui::{
|
use wgui::{
|
||||||
animation::{Animation, AnimationEasing},
|
animation::{Animation, AnimationEasing},
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
|
color::WguiColorName,
|
||||||
components::{self, button::ButtonClickCallback},
|
components::{self, button::ButtonClickCallback},
|
||||||
drawing,
|
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, LayoutTask, WidgetID},
|
layout::{Layout, LayoutTask, WidgetID},
|
||||||
parser::{Fetchable, ParseDocumentParams},
|
parser::{Fetchable, ParseDocumentParams},
|
||||||
|
|
@ -55,6 +55,7 @@ pub fn create_label(layout: &mut Layout, id_parent: WidgetID, content: Translati
|
||||||
wrap: true,
|
wrap: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -70,10 +71,11 @@ pub fn create_label_error(layout: &mut Layout, parent: WidgetID, content: String
|
||||||
content: Translation::from_raw_text_string(content),
|
content: Translation::from_raw_text_string(content),
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
wrap: true,
|
wrap: true,
|
||||||
color: Some(drawing::Color::new(1.0, 0.5, 0.0, 1.0)),
|
color: Some(WguiColorName::Danger.into()),
|
||||||
weight: Some(FontWeight::Bold),
|
weight: Some(FontWeight::Bold),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -84,8 +86,9 @@ pub fn create_label_error(layout: &mut Layout, parent: WidgetID, content: String
|
||||||
|
|
||||||
pub fn create_icon(layout: &mut Layout, id_parent: WidgetID, size: Vec2, path: AssetPath) -> anyhow::Result<WidgetID> {
|
pub fn create_icon(layout: &mut Layout, id_parent: WidgetID, size: Vec2, path: AssetPath) -> anyhow::Result<WidgetID> {
|
||||||
let widget_sprite = WidgetSprite::create(WidgetSpriteParams {
|
let widget_sprite = WidgetSprite::create(WidgetSpriteParams {
|
||||||
color: None,
|
color: Some(WguiColorName::OnBackground.into()),
|
||||||
glyph_data: Some(CustomGlyphData::from_assets(&layout.state.globals, path)?),
|
glyph_data: Some(CustomGlyphData::from_assets(&layout.state.globals, path)?),
|
||||||
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
let size = taffy::Size {
|
let size = taffy::Size {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
use std::{collections::HashMap, rc::Rc, str::FromStr};
|
use std::{collections::HashMap, rc::Rc, str::FromStr};
|
||||||
|
use strum::VariantNames;
|
||||||
use strum::{AsRefStr, EnumString, VariantNames};
|
|
||||||
use wayvr_ipc::packet_client::{PositionMode, WvrProcessLaunchParams};
|
use wayvr_ipc::packet_client::{PositionMode, WvrProcessLaunchParams};
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::{button::ComponentButton, checkbox::ComponentCheckbox, radio_group::ComponentRadioGroup},
|
components::{
|
||||||
|
ComponentTrait, button::ComponentButton, checkbox::ComponentCheckbox, radio_group::ComponentRadioGroup,
|
||||||
|
},
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
|
|
@ -12,7 +13,11 @@ use wgui::{
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
widget::label::WidgetLabel,
|
widget::label::WidgetLabel,
|
||||||
};
|
};
|
||||||
use wlx_common::{config::GeneralConfig, dash_interface::BoxDashInterface, desktop_finder::DesktopEntry};
|
use wlx_common::{
|
||||||
|
config::{AppCompositorMode, AppOrientationMode, AppPosMode, AppResMode, GeneralConfig, PinnedApp},
|
||||||
|
dash_interface::BoxDashInterface,
|
||||||
|
desktop_finder::DesktopEntry,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::{FrontendTask, FrontendTasks, SoundType},
|
frontend::{FrontendTask, FrontendTasks, SoundType},
|
||||||
|
|
@ -20,51 +25,23 @@ use crate::{
|
||||||
views::{ViewTrait, ViewUpdateParams},
|
views::{ViewTrait, ViewUpdateParams},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
|
||||||
enum PosMode {
|
|
||||||
Floating,
|
|
||||||
Anchored,
|
|
||||||
Static,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
|
||||||
enum ResMode {
|
|
||||||
Res1440,
|
|
||||||
Res1080,
|
|
||||||
Res720,
|
|
||||||
Res480,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
|
||||||
enum OrientationMode {
|
|
||||||
Wide,
|
|
||||||
SemiWide,
|
|
||||||
Square,
|
|
||||||
SemiTall,
|
|
||||||
Tall,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
|
||||||
enum CompositorMode {
|
|
||||||
Cage,
|
|
||||||
Native,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Task {
|
enum Task {
|
||||||
SetCompositor(CompositorMode),
|
SetCompositor(AppCompositorMode),
|
||||||
SetRes(ResMode),
|
SetRes(AppResMode),
|
||||||
SetOrientation(OrientationMode),
|
SetOrientation(AppOrientationMode),
|
||||||
SetAutoStart(bool),
|
SetAutoStart(bool),
|
||||||
Launch,
|
Launch,
|
||||||
|
PinApp,
|
||||||
|
UnpinApp,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LaunchParams<'a, T> {
|
struct LaunchParams<'a, T> {
|
||||||
application: &'a DesktopEntry,
|
application: &'a DesktopEntry,
|
||||||
compositor_mode: CompositorMode,
|
compositor_mode: AppCompositorMode,
|
||||||
pos_mode: PosMode,
|
pos_mode: AppPosMode,
|
||||||
res_mode: ResMode,
|
res_mode: AppResMode,
|
||||||
orientation_mode: OrientationMode,
|
orientation_mode: AppOrientationMode,
|
||||||
globals: &'a WguiGlobals,
|
globals: &'a WguiGlobals,
|
||||||
frontend_tasks: &'a FrontendTasks,
|
frontend_tasks: &'a FrontendTasks,
|
||||||
interface: &'a mut BoxDashInterface<T>,
|
interface: &'a mut BoxDashInterface<T>,
|
||||||
|
|
@ -88,14 +65,17 @@ pub struct View {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
radio_orientation: Rc<ComponentRadioGroup>,
|
radio_orientation: Rc<ComponentRadioGroup>,
|
||||||
|
|
||||||
compositor_mode: CompositorMode,
|
compositor_mode: AppCompositorMode,
|
||||||
pos_mode: PosMode,
|
pos_mode: AppPosMode,
|
||||||
res_mode: ResMode,
|
res_mode: AppResMode,
|
||||||
orientation_mode: OrientationMode,
|
orientation_mode: AppOrientationMode,
|
||||||
|
|
||||||
|
pinned_app: Option<PinnedApp>,
|
||||||
|
|
||||||
auto_start: bool,
|
auto_start: bool,
|
||||||
|
|
||||||
on_launched: Option<Box<dyn FnOnce()>>,
|
on_close_request: Option<Box<dyn FnOnce()>>,
|
||||||
|
on_app_pins_changed: Option<Box<dyn Fn()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Params<'a> {
|
pub struct Params<'a> {
|
||||||
|
|
@ -105,7 +85,9 @@ pub struct Params<'a> {
|
||||||
pub parent_id: WidgetID,
|
pub parent_id: WidgetID,
|
||||||
pub config: &'a GeneralConfig,
|
pub config: &'a GeneralConfig,
|
||||||
pub frontend_tasks: &'a FrontendTasks,
|
pub frontend_tasks: &'a FrontendTasks,
|
||||||
pub on_launched: Box<dyn FnOnce()>,
|
pub on_close_request: Box<dyn FnOnce()>,
|
||||||
|
pub on_app_pins_changed: Box<dyn Fn()>,
|
||||||
|
pub pinned_app: Option<PinnedApp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewTrait for View {
|
impl ViewTrait for View {
|
||||||
|
|
@ -131,6 +113,8 @@ impl View {
|
||||||
let cb_autostart = state.fetch_component_as::<ComponentCheckbox>("cb_autostart")?;
|
let cb_autostart = state.fetch_component_as::<ComponentCheckbox>("cb_autostart")?;
|
||||||
|
|
||||||
let btn_launch = state.fetch_component_as::<ComponentButton>("btn_launch")?;
|
let btn_launch = state.fetch_component_as::<ComponentButton>("btn_launch")?;
|
||||||
|
let btn_pin = state.fetch_component_as::<ComponentButton>("btn_pin")?;
|
||||||
|
let btn_unpin = state.fetch_component_as::<ComponentButton>("btn_unpin")?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut label_exec = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "label_exec")?;
|
let mut label_exec = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "label_exec")?;
|
||||||
|
|
@ -145,6 +129,16 @@ impl View {
|
||||||
|
|
||||||
tasks.handle_button(&btn_launch, Task::Launch);
|
tasks.handle_button(&btn_launch, Task::Launch);
|
||||||
|
|
||||||
|
if params.pinned_app.is_some() {
|
||||||
|
// "Unpin app"
|
||||||
|
tasks.handle_button(&btn_unpin, Task::UnpinApp);
|
||||||
|
params.layout.remove_widget(btn_pin.base().get_id());
|
||||||
|
} else {
|
||||||
|
// "Pin app"
|
||||||
|
tasks.handle_button(&btn_pin, Task::PinApp);
|
||||||
|
params.layout.remove_widget(btn_unpin.base().get_id());
|
||||||
|
}
|
||||||
|
|
||||||
let id_icon_parent = state.get_widget_id("icon_parent")?;
|
let id_icon_parent = state.get_widget_id("icon_parent")?;
|
||||||
|
|
||||||
// app icon
|
// app icon
|
||||||
|
|
@ -160,28 +154,35 @@ impl View {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let compositor_mode = if params.config.xwayland_by_default {
|
let compositor_mode = match ¶ms.pinned_app {
|
||||||
CompositorMode::Cage
|
Some(pinned_app) => pinned_app.compositor_mode,
|
||||||
} else {
|
None => {
|
||||||
CompositorMode::Native
|
if params.config.xwayland_by_default {
|
||||||
|
AppCompositorMode::Cage
|
||||||
|
} else {
|
||||||
|
AppCompositorMode::Native
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
radio_compositor.set_value_simple(compositor_mode.as_ref())?;
|
|
||||||
tasks.push(Task::SetCompositor(compositor_mode));
|
|
||||||
|
|
||||||
let res_mode = ResMode::Res1080;
|
|
||||||
// TODO: configurable defaults ?
|
// TODO: configurable defaults ?
|
||||||
//radio_res.set_value(res_mode.as_ref())?;
|
let mut res_mode = AppResMode::Res1080;
|
||||||
//tasks.push(Task::SetRes(res_mode));
|
let mut orientation_mode = AppOrientationMode::Wide;
|
||||||
|
let pos_mode = AppPosMode::Anchored;
|
||||||
|
|
||||||
let orientation_mode = OrientationMode::Wide;
|
if let Some(pinned_app) = ¶ms.pinned_app {
|
||||||
// TODO: configurable defaults ?
|
res_mode = pinned_app.res_mode;
|
||||||
//radio_orientation.set_value(orientation_mode.as_ref())?;
|
orientation_mode = pinned_app.orientation_mode;
|
||||||
//tasks.push(Task::SetOrientation(orientation_mode));
|
}
|
||||||
|
|
||||||
let pos_mode = PosMode::Anchored;
|
// update radios
|
||||||
// TODO: configurable defaults ?
|
{
|
||||||
//radio_pos.set_value(pos_mode.as_ref())?;
|
let mut common = params.layout.common();
|
||||||
//tasks.push(Task::SetPos(pos_mode));
|
// TODO: pos_mode is disabled as for now
|
||||||
|
radio_compositor.set_value(&mut common, compositor_mode.as_ref())?;
|
||||||
|
radio_res.set_value(&mut common, res_mode.as_ref())?;
|
||||||
|
radio_orientation.set_value(&mut common, orientation_mode.as_ref())?;
|
||||||
|
}
|
||||||
|
|
||||||
let auto_start = false;
|
let auto_start = false;
|
||||||
|
|
||||||
|
|
@ -189,11 +190,11 @@ impl View {
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
Box::new(move |_, ev| {
|
Box::new(move |_, ev| {
|
||||||
if let Some(mode) = ev.value.and_then(|v| {
|
if let Some(mode) = ev.value.and_then(|v| {
|
||||||
CompositorMode::from_str(&v)
|
AppCompositorMode::from_str(&v)
|
||||||
.inspect_err(|_| {
|
.inspect_err(|_| {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Invalid value for compositor: '{v}'. Valid values are: {:?}",
|
"Invalid value for compositor: '{v}'. Valid values are: {:?}",
|
||||||
ResMode::VARIANTS
|
AppResMode::VARIANTS
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
|
|
@ -208,11 +209,11 @@ impl View {
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
Box::new(move |_, ev| {
|
Box::new(move |_, ev| {
|
||||||
if let Some(mode) = ev.value.and_then(|v| {
|
if let Some(mode) = ev.value.and_then(|v| {
|
||||||
ResMode::from_str(&v)
|
AppResMode::from_str(&v)
|
||||||
.inspect_err(|_| {
|
.inspect_err(|_| {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Invalid value for resolution: '{v}'. Valid values are: {:?}",
|
"Invalid value for resolution: '{v}'. Valid values are: {:?}",
|
||||||
ResMode::VARIANTS
|
AppResMode::VARIANTS
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
|
|
@ -246,11 +247,11 @@ impl View {
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
Box::new(move |_, ev| {
|
Box::new(move |_, ev| {
|
||||||
if let Some(mode) = ev.value.and_then(|v| {
|
if let Some(mode) = ev.value.and_then(|v| {
|
||||||
OrientationMode::from_str(&v)
|
AppOrientationMode::from_str(&v)
|
||||||
.inspect_err(|_| {
|
.inspect_err(|_| {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Invalid value for orientation: '{v}'. Valid values are: {:?}",
|
"Invalid value for orientation: '{v}'. Valid values are: {:?}",
|
||||||
OrientationMode::VARIANTS
|
AppOrientationMode::VARIANTS
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
|
|
@ -290,23 +291,29 @@ impl View {
|
||||||
entry: params.entry,
|
entry: params.entry,
|
||||||
frontend_tasks: params.frontend_tasks.clone(),
|
frontend_tasks: params.frontend_tasks.clone(),
|
||||||
globals: params.globals.clone(),
|
globals: params.globals.clone(),
|
||||||
on_launched: Some(params.on_launched),
|
on_close_request: Some(params.on_close_request),
|
||||||
|
on_app_pins_changed: Some(params.on_app_pins_changed),
|
||||||
|
pinned_app: params.pinned_app,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) -> anyhow::Result<()> {
|
pub fn update<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) -> anyhow::Result<()> {
|
||||||
loop {
|
while !self.tasks.is_empty() {
|
||||||
let tasks = self.tasks.drain();
|
for task in self.tasks.drain() {
|
||||||
if tasks.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for task in tasks {
|
|
||||||
match task {
|
match task {
|
||||||
Task::SetCompositor(mode) => self.compositor_mode = mode,
|
Task::SetCompositor(mode) => self.compositor_mode = mode,
|
||||||
Task::SetRes(mode) => self.res_mode = mode,
|
Task::SetRes(mode) => self.res_mode = mode,
|
||||||
Task::SetOrientation(mode) => self.orientation_mode = mode,
|
Task::SetOrientation(mode) => self.orientation_mode = mode,
|
||||||
Task::SetAutoStart(auto_start) => self.auto_start = auto_start,
|
Task::SetAutoStart(auto_start) => self.auto_start = auto_start,
|
||||||
Task::Launch => self.action_launch(interface, data),
|
Task::Launch => self.action_launch(interface, data),
|
||||||
|
Task::PinApp => {
|
||||||
|
self.action_pin_app(interface.general_config(data));
|
||||||
|
interface.config_changed(data, Default::default());
|
||||||
|
}
|
||||||
|
Task::UnpinApp => {
|
||||||
|
self.action_unpin_app(interface.general_config(data));
|
||||||
|
interface.config_changed(data, Default::default());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -314,6 +321,49 @@ impl View {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn close(&mut self) {
|
||||||
|
if let Some(c) = self.on_close_request.take() {
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn action_unpin_app(&mut self, config: &mut GeneralConfig) {
|
||||||
|
let Some(pinned_app) = &self.pinned_app else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
self.frontend_tasks.push(FrontendTask::PlaySound(SoundType::Save));
|
||||||
|
config.pinned_apps.retain(|p| p != pinned_app);
|
||||||
|
|
||||||
|
if let Some(c) = &self.on_app_pins_changed {
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn action_pin_app(&mut self, config: &mut GeneralConfig) {
|
||||||
|
self
|
||||||
|
.frontend_tasks
|
||||||
|
.push(FrontendTask::PushToast(Translation::from_translation_key(
|
||||||
|
"SAVED_TO_FAVOURITES",
|
||||||
|
)));
|
||||||
|
self.frontend_tasks.push(FrontendTask::PlaySound(SoundType::Save));
|
||||||
|
|
||||||
|
config.pinned_apps.push(PinnedApp {
|
||||||
|
app_id: self.entry.app_id.clone(),
|
||||||
|
compositor_mode: self.compositor_mode,
|
||||||
|
pos_mode: self.pos_mode,
|
||||||
|
orientation_mode: self.orientation_mode,
|
||||||
|
res_mode: self.res_mode,
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(c) = &self.on_app_pins_changed {
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
|
||||||
fn action_launch<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
fn action_launch<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
||||||
View::try_launch(LaunchParams {
|
View::try_launch(LaunchParams {
|
||||||
application: &self.entry,
|
application: &self.entry,
|
||||||
|
|
@ -326,7 +376,7 @@ impl View {
|
||||||
auto_start: self.auto_start,
|
auto_start: self.auto_start,
|
||||||
interface,
|
interface,
|
||||||
data,
|
data,
|
||||||
on_launched: self.on_launched.take(),
|
on_launched: self.on_close_request.take(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,7 +397,7 @@ impl View {
|
||||||
fn launch<T>(mut params: LaunchParams<T>) -> anyhow::Result<()> {
|
fn launch<T>(mut params: LaunchParams<T>) -> anyhow::Result<()> {
|
||||||
let mut env = Vec::<String>::new();
|
let mut env = Vec::<String>::new();
|
||||||
|
|
||||||
if params.compositor_mode == CompositorMode::Native {
|
if params.compositor_mode == AppCompositorMode::Native {
|
||||||
// This list could be larger, feel free to expand it
|
// This list could be larger, feel free to expand it
|
||||||
env.push("QT_QPA_PLATFORM=wayland".into());
|
env.push("QT_QPA_PLATFORM=wayland".into());
|
||||||
env.push("GDK_BACKEND=wayland".into());
|
env.push("GDK_BACKEND=wayland".into());
|
||||||
|
|
@ -357,19 +407,19 @@ impl View {
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = match params.compositor_mode {
|
let args = match params.compositor_mode {
|
||||||
CompositorMode::Cage => format!("-- {} {}", params.application.exec_path, params.application.exec_args),
|
AppCompositorMode::Cage => format!("-- {} {}", params.application.exec_path, params.application.exec_args),
|
||||||
CompositorMode::Native => params.application.exec_args.to_string(),
|
AppCompositorMode::Native => params.application.exec_args.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let exec = match params.compositor_mode {
|
let exec = match params.compositor_mode {
|
||||||
CompositorMode::Cage => "cage".to_string(),
|
AppCompositorMode::Cage => "cage".to_string(),
|
||||||
CompositorMode::Native => params.application.exec_path.to_string(),
|
AppCompositorMode::Native => params.application.exec_path.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let pos_mode = match params.pos_mode {
|
let pos_mode = match params.pos_mode {
|
||||||
PosMode::Floating => PositionMode::Float,
|
AppPosMode::Floating => PositionMode::Float,
|
||||||
PosMode::Anchored => PositionMode::Anchor,
|
AppPosMode::Anchored => PositionMode::Anchor,
|
||||||
PosMode::Static => PositionMode::Static,
|
AppPosMode::Static => PositionMode::Static,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut userdata = HashMap::new();
|
let mut userdata = HashMap::new();
|
||||||
|
|
@ -408,20 +458,20 @@ impl View {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_resolution(res_mode: ResMode, orientation_mode: OrientationMode) -> [u32; 2] {
|
fn calculate_resolution(res_mode: AppResMode, orientation_mode: AppOrientationMode) -> [u32; 2] {
|
||||||
let total_pixels = match res_mode {
|
let total_pixels = match res_mode {
|
||||||
ResMode::Res1440 => 2560 * 1440,
|
AppResMode::Res1440 => 2560 * 1440,
|
||||||
ResMode::Res1080 => 1920 * 1080,
|
AppResMode::Res1080 => 1920 * 1080,
|
||||||
ResMode::Res720 => 1280 * 720,
|
AppResMode::Res720 => 1280 * 720,
|
||||||
ResMode::Res480 => 854 * 480,
|
AppResMode::Res480 => 854 * 480,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (ratio_w, ratio_h) = match orientation_mode {
|
let (ratio_w, ratio_h) = match orientation_mode {
|
||||||
OrientationMode::Wide => (16, 9),
|
AppOrientationMode::Wide => (16, 9),
|
||||||
OrientationMode::SemiWide => (3, 2),
|
AppOrientationMode::SemiWide => (3, 2),
|
||||||
OrientationMode::Square => (1, 1),
|
AppOrientationMode::Square => (1, 1),
|
||||||
OrientationMode::SemiTall => (2, 3),
|
AppOrientationMode::SemiTall => (2, 3),
|
||||||
OrientationMode::Tall => (9, 16),
|
AppOrientationMode::Tall => (9, 16),
|
||||||
};
|
};
|
||||||
|
|
||||||
let k = ((total_pixels as f64) / (ratio_w * ratio_h) as f64).sqrt();
|
let k = ((total_pixels as f64) / (ratio_w * ratio_h) as f64).sqrt();
|
||||||
|
|
@ -433,13 +483,20 @@ impl View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, entry: DesktopEntry, popup: PopupHolder<View>) {
|
pub fn mount_popup(
|
||||||
|
frontend_tasks: FrontendTasks,
|
||||||
|
globals: WguiGlobals,
|
||||||
|
entry: DesktopEntry,
|
||||||
|
popup: PopupHolder<View>,
|
||||||
|
on_app_pins_changed: Box<dyn Fn()>,
|
||||||
|
pinned_app: Option<PinnedApp>,
|
||||||
|
) {
|
||||||
frontend_tasks
|
frontend_tasks
|
||||||
.clone()
|
.clone()
|
||||||
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
|
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
|
||||||
Translation::from_raw_text(&entry.app_name),
|
Translation::from_raw_text(&entry.app_name),
|
||||||
Box::new(move |data| {
|
Box::new(move |data| {
|
||||||
let on_launched = popup.get_close_callback(data.layout);
|
let on_close_request = popup.get_close_callback(data.layout);
|
||||||
let view = View::new(Params {
|
let view = View::new(Params {
|
||||||
entry: entry.clone(),
|
entry: entry.clone(),
|
||||||
globals: &globals,
|
globals: &globals,
|
||||||
|
|
@ -447,7 +504,9 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, entry: D
|
||||||
parent_id: data.id_content,
|
parent_id: data.id_content,
|
||||||
frontend_tasks: &frontend_tasks,
|
frontend_tasks: &frontend_tasks,
|
||||||
config: data.config,
|
config: data.config,
|
||||||
on_launched,
|
on_close_request,
|
||||||
|
on_app_pins_changed,
|
||||||
|
pinned_app,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
popup.set_view(data.handle, view, None);
|
popup.set_view(data.handle, view, None);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
|
color::{WguiColor, WguiColorName},
|
||||||
components::{
|
components::{
|
||||||
self,
|
self,
|
||||||
button::{ButtonClickCallback, ComponentButton},
|
button::{ButtonClickCallback, ComponentButton},
|
||||||
|
|
@ -110,11 +111,13 @@ struct MultiSelectorParams<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
|
fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
|
||||||
let accent_color = params.ess.layout.state.theme.accent_color;
|
|
||||||
|
|
||||||
for cell in params.cells {
|
for cell in params.cells {
|
||||||
let highlighted = cell.key == params.def_cell;
|
let highlighted = cell.key == params.def_cell;
|
||||||
let color = if highlighted { Some(accent_color) } else { None };
|
let color = if highlighted {
|
||||||
|
Some(WguiColor::from(WguiColorName::Primary))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// button
|
// button
|
||||||
let (_, button) = components::button::construct(
|
let (_, button) = components::button::construct(
|
||||||
|
|
@ -664,11 +667,11 @@ impl View {
|
||||||
|
|
||||||
let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| {
|
let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| {
|
||||||
let color = if num == btn_num {
|
let color = if num == btn_num {
|
||||||
com.state.theme.accent_color
|
WguiColorName::Primary
|
||||||
} else {
|
} else {
|
||||||
com.state.theme.button_color
|
WguiColorName::BackgroundVariant
|
||||||
};
|
};
|
||||||
btn.set_color(&mut com, color);
|
btn.set_color(&mut com, color.into());
|
||||||
};
|
};
|
||||||
|
|
||||||
perform(0, &self.btn_sinks);
|
perform(0, &self.btn_sinks);
|
||||||
|
|
|
||||||
|
|
@ -384,13 +384,15 @@ fn input_controls_for_action(
|
||||||
|
|
||||||
input_controls_for_hand(
|
input_controls_for_hand(
|
||||||
mp,
|
mp,
|
||||||
parent,
|
InputControlsForHandParams {
|
||||||
current_left,
|
parent,
|
||||||
XrInputSide::Left,
|
current: current_left,
|
||||||
action.clone(),
|
side: XrInputSide::Left,
|
||||||
click_type,
|
action: &action,
|
||||||
profile,
|
click_type,
|
||||||
current.threshold_left,
|
profile,
|
||||||
|
threshold: current.threshold_left,
|
||||||
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let current_right = current.right.as_ref().map(|x| match x {
|
let current_right = current.right.as_ref().map(|x| match x {
|
||||||
|
|
@ -400,33 +402,40 @@ fn input_controls_for_action(
|
||||||
|
|
||||||
input_controls_for_hand(
|
input_controls_for_hand(
|
||||||
mp,
|
mp,
|
||||||
parent,
|
InputControlsForHandParams {
|
||||||
current_right,
|
parent,
|
||||||
XrInputSide::Right,
|
current: current_right,
|
||||||
action,
|
side: XrInputSide::Right,
|
||||||
click_type,
|
action: &action,
|
||||||
profile,
|
click_type,
|
||||||
current.threshold_right,
|
profile,
|
||||||
)
|
threshold: current.threshold_right,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_controls_for_hand(
|
struct InputControlsForHandParams<'a> {
|
||||||
mp: &mut MacroParams,
|
|
||||||
parent: WidgetID,
|
parent: WidgetID,
|
||||||
current: Option<&str>,
|
current: Option<&'a str>,
|
||||||
side: XrInputSide,
|
side: XrInputSide,
|
||||||
action: Rc<str>,
|
action: &'a Rc<str>,
|
||||||
click_type: ClickType,
|
click_type: ClickType,
|
||||||
profile: &XrControllerProfile,
|
profile: &'a XrControllerProfile,
|
||||||
threshold: Option<[f32; 2]>,
|
threshold: Option<[f32; 2]>,
|
||||||
) -> anyhow::Result<()> {
|
}
|
||||||
let Some(user_path) = profile.find_userpath(side) else {
|
|
||||||
|
fn input_controls_for_hand(mp: &mut MacroParams, par: InputControlsForHandParams) -> anyhow::Result<()> {
|
||||||
|
let Some(user_path) = par.profile.find_userpath(par.side) else {
|
||||||
return Ok(()); // this hand is not available
|
return Ok(()); // this hand is not available
|
||||||
};
|
};
|
||||||
|
|
||||||
let current = current.and_then(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok());
|
let current = par
|
||||||
|
.current
|
||||||
|
.and_then(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok());
|
||||||
|
|
||||||
let parent = horiz_cell(mp.layout, parent)?;
|
let parent = horiz_cell(mp.layout, par.parent)?;
|
||||||
|
|
||||||
let available_components: Rc<[XrInputComponent]> = current
|
let available_components: Rc<[XrInputComponent]> = current
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
@ -445,8 +454,8 @@ fn input_controls_for_hand(
|
||||||
subpath_dropdown(
|
subpath_dropdown(
|
||||||
mp,
|
mp,
|
||||||
parent,
|
parent,
|
||||||
action.clone(),
|
par.action.clone(),
|
||||||
side,
|
par.side,
|
||||||
available_subpaths,
|
available_subpaths,
|
||||||
current.as_ref().map(|x| x.subpath),
|
current.as_ref().map(|x| x.subpath),
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -454,22 +463,22 @@ fn input_controls_for_hand(
|
||||||
if !component_dropdown(
|
if !component_dropdown(
|
||||||
mp,
|
mp,
|
||||||
parent,
|
parent,
|
||||||
action.clone(),
|
par.action.clone(),
|
||||||
side,
|
par.side,
|
||||||
available_components,
|
available_components,
|
||||||
current.as_ref().map(|x| x.component),
|
current.as_ref().map(|x| x.component),
|
||||||
)? {
|
)? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
clicks_dropdown(mp, parent, action.clone(), click_type)?;
|
clicks_dropdown(mp, parent, par.action.clone(), par.click_type)?;
|
||||||
|
|
||||||
if let Some(component) = current.as_ref().map(|x| x.component)
|
if let Some(component) = current.as_ref().map(|x| x.component)
|
||||||
&& component.is_analog()
|
&& component.is_analog()
|
||||||
&& &*action != "scroll"
|
&& &**par.action != "scroll"
|
||||||
// hax
|
// hax
|
||||||
{
|
{
|
||||||
threshold_slider(mp, parent, action, side, threshold)?;
|
threshold_slider(mp, parent, par.action.clone(), par.side, par.threshold)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
use crate::{
|
||||||
|
frontend::{FrontendTask, FrontendTasks},
|
||||||
|
tab::TabType,
|
||||||
|
util::popup_manager::{MountPopupOnceParams, PopupHolder},
|
||||||
|
views::{ViewTrait, ViewUpdateParams},
|
||||||
|
};
|
||||||
|
use std::{rc::Rc, sync::Arc};
|
||||||
|
use wgui::color::WguiColorName;
|
||||||
|
use wgui::{
|
||||||
|
assets::AssetPath,
|
||||||
|
components::button::ComponentButton,
|
||||||
|
globals::WguiGlobals,
|
||||||
|
i18n::Translation,
|
||||||
|
layout::{Layout, LayoutTask, WidgetID},
|
||||||
|
log::LogErr,
|
||||||
|
palette::PALETTES,
|
||||||
|
parser::{Fetchable, ParseDocumentParams, TemplateParams},
|
||||||
|
task::Tasks,
|
||||||
|
};
|
||||||
|
use wlx_common::{
|
||||||
|
dash_interface::ConfigChangeKind,
|
||||||
|
palette::{list_palette_files, load_custom_palette},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum Task {
|
||||||
|
SelectPalette(String),
|
||||||
|
CustomPaletteUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Params<'a> {
|
||||||
|
pub globals: WguiGlobals,
|
||||||
|
pub layout: &'a mut Layout,
|
||||||
|
pub parent_id: WidgetID,
|
||||||
|
pub frontend_tasks: &'a FrontendTasks,
|
||||||
|
pub on_close_request: Box<dyn FnOnce()>,
|
||||||
|
pub current_palette: Arc<str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct View {
|
||||||
|
tasks: Tasks<Task>,
|
||||||
|
frontend_tasks: FrontendTasks,
|
||||||
|
on_close_request: Option<Box<dyn FnOnce()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ViewTrait for View {
|
||||||
|
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||||
|
for task in self.tasks.drain() {
|
||||||
|
match task {
|
||||||
|
Task::SelectPalette(profile) => {
|
||||||
|
let mut globals = par.layout.state.globals.get();
|
||||||
|
let new_palette = wlx_common::palette::load_palette(&profile);
|
||||||
|
globals.palette = new_palette;
|
||||||
|
par.general_config.color_palette = profile.into();
|
||||||
|
par.layout.tasks.push(LayoutTask::RefreshPalette);
|
||||||
|
// this works because LookAndFeel is the first tab
|
||||||
|
self.frontend_tasks.push(FrontendTask::SetTab(TabType::Settings));
|
||||||
|
par.config_change_kind.replace(ConfigChangeKind::WguiColorPaletteChange);
|
||||||
|
if let Some(c) = self.on_close_request.take() {
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task::CustomPaletteUrl => {
|
||||||
|
self.frontend_tasks.push(FrontendTask::OpenURL(
|
||||||
|
"https://wayvr.org/docs/basics/customization/".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! insert_colors {
|
||||||
|
(
|
||||||
|
$params:expr,
|
||||||
|
$palette:expr,
|
||||||
|
$( $key:literal => $color:ident ),* $(,)?
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
$params.insert_str(
|
||||||
|
$key,
|
||||||
|
WguiColorName::$color
|
||||||
|
.to_wgui_color()
|
||||||
|
.resolve($palette)
|
||||||
|
.to_hex()
|
||||||
|
);
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View {
|
||||||
|
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||||
|
let doc_params = &ParseDocumentParams {
|
||||||
|
globals: params.globals.clone(),
|
||||||
|
path: AssetPath::BuiltIn("gui/view/color_palettes.xml"),
|
||||||
|
extra: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut parser_state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
||||||
|
|
||||||
|
let list_parent = parser_state.fetch_widget(¶ms.layout.state, "list_parent")?.id;
|
||||||
|
|
||||||
|
let tasks = Tasks::new();
|
||||||
|
|
||||||
|
for (idx, name) in list_palette_files().into_iter().enumerate() {
|
||||||
|
let Ok(palette) = load_custom_palette(&name).log_warn("Could not load custom color palette") else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = format!("profile_custom_{idx}");
|
||||||
|
let is_current = &*params.current_palette == name.as_str();
|
||||||
|
|
||||||
|
let mut cell_params = TemplateParams::new();
|
||||||
|
cell_params.insert("id", &id);
|
||||||
|
|
||||||
|
let display_name = &name[..name.len() - 5];
|
||||||
|
|
||||||
|
if is_current {
|
||||||
|
cell_params.insert_str("text", format!("{display_name} ✅"));
|
||||||
|
cell_params.insert("tooltip", "APP_SETTINGS.COLOR_PALETTE_CURRENT");
|
||||||
|
} else {
|
||||||
|
cell_params.insert("text", display_name);
|
||||||
|
cell_params.insert("tooltip", "APP_SETTINGS.COLOR_PALETTE_ACTIVATE");
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_colors!(
|
||||||
|
cell_params,
|
||||||
|
&palette,
|
||||||
|
"primary" => Primary,
|
||||||
|
"on_primary" => OnPrimary,
|
||||||
|
"secondary" => Secondary,
|
||||||
|
"on_secondary" => OnSecondary,
|
||||||
|
"tertiary" => Tertiary,
|
||||||
|
"on_tertiary" => OnTertiary,
|
||||||
|
"danger" => Danger,
|
||||||
|
"on_danger" => OnDanger,
|
||||||
|
"background" => Background,
|
||||||
|
"on_background" => OnBackground,
|
||||||
|
"background_variant" => BackgroundVariant,
|
||||||
|
"outline" => Outline,
|
||||||
|
"highlight" => Highlight,
|
||||||
|
);
|
||||||
|
|
||||||
|
parser_state.instantiate_template(
|
||||||
|
doc_params,
|
||||||
|
"ColorPaletteButton",
|
||||||
|
params.layout,
|
||||||
|
list_parent,
|
||||||
|
cell_params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if !is_current {
|
||||||
|
let btn = parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
|
let tasks_clone = tasks.clone();
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks_clone.push(Task::SelectPalette(name.to_string()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, (name, palette)) in PALETTES.iter().enumerate() {
|
||||||
|
let id = format!("profile_builtin_{idx}");
|
||||||
|
let is_current = &*params.current_palette == *name;
|
||||||
|
|
||||||
|
let mut cell_params = TemplateParams::new();
|
||||||
|
cell_params.insert("id", &id);
|
||||||
|
|
||||||
|
if is_current {
|
||||||
|
cell_params.insert_str("text", format!("{name} ✅"));
|
||||||
|
cell_params.insert("tooltip", "APP_SETTINGS.COLOR_PALETTE_CURRENT");
|
||||||
|
} else {
|
||||||
|
cell_params.insert("text", name);
|
||||||
|
cell_params.insert("tooltip", "APP_SETTINGS.COLOR_PALETTE_ACTIVATE");
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_colors!(
|
||||||
|
cell_params,
|
||||||
|
palette,
|
||||||
|
"primary" => Primary,
|
||||||
|
"on_primary" => OnPrimary,
|
||||||
|
"secondary" => Secondary,
|
||||||
|
"on_secondary" => OnSecondary,
|
||||||
|
"tertiary" => Tertiary,
|
||||||
|
"on_tertiary" => OnTertiary,
|
||||||
|
"danger" => Danger,
|
||||||
|
"on_danger" => OnDanger,
|
||||||
|
"background" => Background,
|
||||||
|
"on_background" => OnBackground,
|
||||||
|
"background_variant" => BackgroundVariant,
|
||||||
|
"outline" => Outline,
|
||||||
|
"highlight" => Highlight,
|
||||||
|
);
|
||||||
|
|
||||||
|
parser_state.instantiate_template(
|
||||||
|
doc_params,
|
||||||
|
"ColorPaletteButton",
|
||||||
|
params.layout,
|
||||||
|
list_parent,
|
||||||
|
cell_params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if !is_current {
|
||||||
|
let btn = parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
|
let tasks_clone = tasks.clone();
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks_clone.push(Task::SelectPalette(name.to_string()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_state.instantiate_template(
|
||||||
|
doc_params,
|
||||||
|
"CustomPaletteButton",
|
||||||
|
params.layout,
|
||||||
|
list_parent,
|
||||||
|
TemplateParams::default(),
|
||||||
|
)?;
|
||||||
|
let btn = parser_state.fetch_component_as::<ComponentButton>("custom_btn")?;
|
||||||
|
let tasks_clone = tasks.clone();
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks_clone.push(Task::CustomPaletteUrl);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
tasks,
|
||||||
|
frontend_tasks: params.frontend_tasks.clone(),
|
||||||
|
on_close_request: Some(params.on_close_request),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mount_popup(
|
||||||
|
frontend_tasks: FrontendTasks,
|
||||||
|
globals: WguiGlobals,
|
||||||
|
popup: PopupHolder<View>,
|
||||||
|
current_palette: Arc<str>,
|
||||||
|
) {
|
||||||
|
frontend_tasks
|
||||||
|
.clone()
|
||||||
|
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
|
||||||
|
Translation::from_translation_key("APP_SETTINGS.COLOR_PALETTES"),
|
||||||
|
Box::new(move |data| {
|
||||||
|
let on_close_request = popup.get_close_callback(data.layout);
|
||||||
|
let view = View::new(Params {
|
||||||
|
globals: globals.clone(),
|
||||||
|
layout: data.layout,
|
||||||
|
parent_id: data.id_content,
|
||||||
|
frontend_tasks: &frontend_tasks,
|
||||||
|
current_palette,
|
||||||
|
on_close_request,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
popup.set_view(data.handle, view, None);
|
||||||
|
Ok(popup.get_close_callback(data.layout))
|
||||||
|
}),
|
||||||
|
Default::default(), /* extra */
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
@ -51,6 +51,9 @@ pub struct View {
|
||||||
id_content: WidgetID,
|
id_content: WidgetID,
|
||||||
on_close_request: Option<Box<dyn FnOnce()>>,
|
on_close_request: Option<Box<dyn FnOnce()>>,
|
||||||
on_downloaded: Option<Box<dyn FnOnce()>>,
|
on_downloaded: Option<Box<dyn FnOnce()>>,
|
||||||
|
|
||||||
|
// will cancel on Drop
|
||||||
|
task_downloader: Option<smol::Task<Option<()>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||||
|
|
@ -63,67 +66,66 @@ fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||||
|
|
||||||
impl ViewTrait for View {
|
impl ViewTrait for View {
|
||||||
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||||
for task in self.tasks.drain() {
|
while !self.tasks.is_empty() {
|
||||||
match task {
|
for task in self.tasks.drain() {
|
||||||
Task::StartDownload(url, path) => {
|
match task {
|
||||||
if let Some(on_downloaded) = self.on_downloaded.take() {
|
Task::StartDownload(url, path) => {
|
||||||
self
|
if let Some(on_downloaded) = self.on_downloaded.take() {
|
||||||
.executor
|
self.task_downloader = Some(self.executor.spawn(View::download(
|
||||||
.spawn(View::download(
|
|
||||||
self.tasks.clone(),
|
self.tasks.clone(),
|
||||||
self.executor.clone(),
|
|
||||||
url,
|
url,
|
||||||
path,
|
path,
|
||||||
on_downloaded,
|
on_downloaded,
|
||||||
))
|
)));
|
||||||
.detach();
|
}
|
||||||
}
|
}
|
||||||
}
|
Task::SetStatusText(text) => {
|
||||||
Task::SetStatusText(text) => {
|
let widgets = &mut par.layout.state.widgets;
|
||||||
let widgets = &mut par.layout.state.widgets;
|
widgets
|
||||||
widgets
|
.fetch(self.id_label_status)?
|
||||||
.fetch(self.id_label_status)?
|
.cast::<WidgetLabel>()?
|
||||||
.cast::<WidgetLabel>()?
|
.set_text(&mut par.layout.common(), Translation::from_raw_text_string(text));
|
||||||
.set_text(&mut par.layout.common(), Translation::from_raw_text_string(text));
|
}
|
||||||
}
|
Task::ShowIconSuccess => {
|
||||||
Task::ShowIconSuccess => {
|
par.layout.remove_children(self.id_loading_parent);
|
||||||
par.layout.remove_children(self.id_loading_parent);
|
wgui_simple::create_icon(
|
||||||
wgui_simple::create_icon(
|
|
||||||
par.layout,
|
|
||||||
self.id_loading_parent,
|
|
||||||
Vec2::splat(32.0),
|
|
||||||
AssetPath::BuiltIn("dashboard/check.svg"),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// "Close window" button
|
|
||||||
self
|
|
||||||
.parser_state
|
|
||||||
.realize_template(
|
|
||||||
&doc_params(&self.globals),
|
|
||||||
"btn_close",
|
|
||||||
par.layout,
|
par.layout,
|
||||||
self.id_content,
|
self.id_loading_parent,
|
||||||
Default::default(),
|
Vec2::splat(32.0),
|
||||||
)?
|
AssetPath::BuiltIn("dashboard/check.svg"),
|
||||||
.fetch_component_as::<ComponentButton>("btn")?
|
)?;
|
||||||
.on_click(self.tasks.get_button_click_callback(Task::Close));
|
|
||||||
}
|
// "Close window" button
|
||||||
Task::ShowIconError => {
|
self
|
||||||
par.layout.remove_children(self.id_loading_parent);
|
.parser_state
|
||||||
wgui_simple::create_icon(
|
.realize_template(
|
||||||
par.layout,
|
&doc_params(&self.globals),
|
||||||
self.id_loading_parent,
|
"btn_close",
|
||||||
Vec2::splat(32.0),
|
par.layout,
|
||||||
AssetPath::BuiltIn("dashboard/error.svg"),
|
self.id_content,
|
||||||
)?;
|
Default::default(),
|
||||||
}
|
)?
|
||||||
Task::Close => {
|
.fetch_component_as::<ComponentButton>("btn")?
|
||||||
if let Some(on_close) = self.on_close_request.take() {
|
.on_click(self.tasks.get_button_click_callback(Task::Close));
|
||||||
on_close();
|
}
|
||||||
|
Task::ShowIconError => {
|
||||||
|
par.layout.remove_children(self.id_loading_parent);
|
||||||
|
wgui_simple::create_icon(
|
||||||
|
par.layout,
|
||||||
|
self.id_loading_parent,
|
||||||
|
Vec2::splat(32.0),
|
||||||
|
AssetPath::BuiltIn("dashboard/error.svg"),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Task::Close => {
|
||||||
|
if let Some(on_close) = self.on_close_request.take() {
|
||||||
|
on_close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,42 +186,18 @@ impl View {
|
||||||
id_content,
|
id_content,
|
||||||
on_close_request: Some(on_close_request),
|
on_close_request: Some(on_close_request),
|
||||||
on_downloaded: Some(par.on_downloaded),
|
on_downloaded: Some(par.on_downloaded),
|
||||||
|
task_downloader: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn download(
|
async fn download(
|
||||||
tasks: Tasks<Task>,
|
tasks: Tasks<Task>,
|
||||||
executor: AsyncExecutor,
|
|
||||||
url: String,
|
url: String,
|
||||||
target_path: PathBuf,
|
target_path: PathBuf,
|
||||||
on_downloaded: Box<dyn FnOnce()>,
|
on_downloaded: Box<dyn FnOnce()>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
tasks.push(Task::SetStatusText(String::from("Connecting to the server...")));
|
tasks.push(Task::SetStatusText(String::from("Connecting to the server...")));
|
||||||
|
|
||||||
// start downloading from the server with progress reporting
|
|
||||||
let res = handle_async_result(
|
|
||||||
"Download failed",
|
|
||||||
&tasks,
|
|
||||||
http_client::get(http_client::GetParams {
|
|
||||||
executor: &executor,
|
|
||||||
url: &url,
|
|
||||||
on_progress: Some(Box::new({
|
|
||||||
let tasks = tasks.clone();
|
|
||||||
move |data: ProgressFuncData| {
|
|
||||||
tasks.push(Task::SetStatusText(format!(
|
|
||||||
"{}/{} KiB ({}%)",
|
|
||||||
data.bytes_downloaded / 1024,
|
|
||||||
data.file_size / 1024,
|
|
||||||
(data.bytes_downloaded as f32 / data.file_size as f32 * 100.0).round()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
})
|
|
||||||
.await,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
tasks.push(Task::SetStatusText(String::from("Writing to file...")));
|
|
||||||
|
|
||||||
// create parent directory if it doesn't exist yet
|
// create parent directory if it doesn't exist yet
|
||||||
if let Some(parent) = target_path.parent() {
|
if let Some(parent) = target_path.parent() {
|
||||||
handle_async_result(
|
handle_async_result(
|
||||||
|
|
@ -229,10 +207,30 @@ impl View {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start downloading from the server with progress reporting
|
||||||
handle_async_result(
|
handle_async_result(
|
||||||
"File write failed",
|
"Download failed",
|
||||||
&tasks,
|
&tasks,
|
||||||
smol::fs::write(target_path, res.data).await,
|
http_client::download_to_file(
|
||||||
|
http_client::GetParams {
|
||||||
|
url: &url,
|
||||||
|
on_progress: Some(Box::new({
|
||||||
|
let tasks = tasks.clone();
|
||||||
|
move |data: ProgressFuncData| {
|
||||||
|
if tasks.len() < 100 {
|
||||||
|
tasks.push(Task::SetStatusText(format!(
|
||||||
|
"{}/{} MiB ({}%)",
|
||||||
|
data.bytes_downloaded / 1024 / 1024,
|
||||||
|
data.file_size / 1024 / 1024,
|
||||||
|
(data.bytes_downloaded as f32 / data.file_size as f32 * 100.0).round()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
&target_path,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
tasks.push(Task::SetStatusText(String::from("Download finished")));
|
tasks.push(Task::SetStatusText(String::from("Download finished")));
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use wgui::{
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
renderer_vk::text::{FontWeight, HorizontalAlign, TextShadow, TextStyle, custom_glyph::CustomGlyphData},
|
renderer_vk::text::{FontWeight, HorizontalAlign, TextStyle, WguiTextShadow, custom_glyph::CustomGlyphData},
|
||||||
taffy::{
|
taffy::{
|
||||||
self, AlignItems, AlignSelf, JustifyContent, JustifySelf,
|
self, AlignItems, AlignSelf, JustifyContent, JustifySelf,
|
||||||
prelude::{auto, length, percent},
|
prelude::{auto, length, percent},
|
||||||
|
|
@ -61,12 +61,8 @@ const GAME_COVER_SIZE_X: f32 = 140.0;
|
||||||
const GAME_COVER_SIZE_Y: f32 = 210.0;
|
const GAME_COVER_SIZE_Y: f32 = 210.0;
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
async fn request_cover_image(
|
async fn request_cover_image(manifest: steam_utils::AppManifest, on_loaded: Box<dyn FnOnce(CoverArt)>) {
|
||||||
executor: AsyncExecutor,
|
let cover_art = match cached_fetcher::request_cover_art(manifest.app_id.clone()).await {
|
||||||
manifest: steam_utils::AppManifest,
|
|
||||||
on_loaded: Box<dyn FnOnce(CoverArt)>,
|
|
||||||
) {
|
|
||||||
let cover_art = match cached_fetcher::request_image(executor, manifest.app_id.clone()).await {
|
|
||||||
Ok(cover_art) => cover_art,
|
Ok(cover_art) => cover_art,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("request_cover_image failed: {:?}", e);
|
log::error!("request_cover_image failed: {:?}", e);
|
||||||
|
|
@ -79,7 +75,7 @@ impl View {
|
||||||
|
|
||||||
fn mount_image(&self, layout: &mut Layout, glyph: &CustomGlyphData) -> anyhow::Result<()> {
|
fn mount_image(&self, layout: &mut Layout, glyph: &CustomGlyphData) -> anyhow::Result<()> {
|
||||||
let image = WidgetImage::create(WidgetImageParams {
|
let image = WidgetImage::create(WidgetImageParams {
|
||||||
round: WLength::Units(10.0),
|
round: WLength::Units(6.0),
|
||||||
glyph_data: Some(glyph.clone()),
|
glyph_data: Some(glyph.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
@ -89,8 +85,8 @@ impl View {
|
||||||
image,
|
image,
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
size: taffy::Size {
|
size: taffy::Size {
|
||||||
width: percent(1.0),
|
width: percent(1.0_f32),
|
||||||
height: percent(1.0),
|
height: percent(1.0_f32),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
@ -107,16 +103,17 @@ impl View {
|
||||||
content: Translation::from_raw_text(text),
|
content: Translation::from_raw_text(text),
|
||||||
style: TextStyle {
|
style: TextStyle {
|
||||||
weight: Some(FontWeight::Bold),
|
weight: Some(FontWeight::Bold),
|
||||||
|
color: Some(drawing::Color::new(1.0, 1.0, 1.0, 1.0).into()),
|
||||||
wrap: true,
|
wrap: true,
|
||||||
size: Some(16.0),
|
size: Some(16.0),
|
||||||
align: Some(HorizontalAlign::Center),
|
align: Some(HorizontalAlign::Center),
|
||||||
shadow: Some(TextShadow {
|
shadow: Some(WguiTextShadow {
|
||||||
color: drawing::Color::new(0.0, 0.0, 0.0, 1.0),
|
color: drawing::Color::new(0.0, 0.0, 0.0, 1.0).into(),
|
||||||
x: 2.0,
|
..Default::default()
|
||||||
y: 2.0,
|
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -125,10 +122,10 @@ impl View {
|
||||||
label,
|
label,
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
position: taffy::Position::Absolute,
|
position: taffy::Position::Absolute,
|
||||||
align_self: Some(AlignSelf::Baseline),
|
align_self: Some(AlignSelf::BASELINE),
|
||||||
justify_self: Some(JustifySelf::Center),
|
justify_self: Some(JustifySelf::CENTER),
|
||||||
margin: taffy::Rect {
|
margin: taffy::Rect {
|
||||||
top: length(32.0),
|
top: length(32.0_f32),
|
||||||
bottom: auto(),
|
bottom: auto(),
|
||||||
left: auto(),
|
left: auto(),
|
||||||
right: auto(),
|
right: auto(),
|
||||||
|
|
@ -173,10 +170,10 @@ impl View {
|
||||||
let (widget_button, button) = components::button::construct(
|
let (widget_button, button) = components::button::construct(
|
||||||
params.ess,
|
params.ess,
|
||||||
components::button::Params {
|
components::button::Params {
|
||||||
color: Some(drawing::Color::new(1.0, 1.0, 1.0, 0.0)),
|
color: Some(drawing::Color::new(1.0, 1.0, 1.0, 0.0).into()),
|
||||||
border_color: Some(BORDER_COLOR_DEFAULT),
|
border_color: Some(BORDER_COLOR_DEFAULT.into()),
|
||||||
hover_border_color: Some(BORDER_COLOR_HOVERED),
|
hover_border_color: Some(BORDER_COLOR_HOVERED.into()),
|
||||||
round: WLength::Units(12.0),
|
round: WLength::Units(8.0),
|
||||||
border: 2.0,
|
border: 2.0,
|
||||||
tooltip: Some(TooltipInfo {
|
tooltip: Some(TooltipInfo {
|
||||||
side: TooltipSide::Bottom,
|
side: TooltipSide::Bottom,
|
||||||
|
|
@ -184,8 +181,8 @@ impl View {
|
||||||
}),
|
}),
|
||||||
style: taffy::Style {
|
style: taffy::Style {
|
||||||
position: taffy::Position::Relative,
|
position: taffy::Position::Relative,
|
||||||
align_items: Some(taffy::AlignItems::Center),
|
align_items: Some(AlignItems::CENTER),
|
||||||
justify_content: Some(taffy::JustifyContent::Center),
|
justify_content: Some(JustifyContent::CENTER),
|
||||||
size: taffy::Size {
|
size: taffy::Size {
|
||||||
width: length(GAME_COVER_SIZE_X * params.scale),
|
width: length(GAME_COVER_SIZE_X * params.scale),
|
||||||
height: length(GAME_COVER_SIZE_Y * params.scale),
|
height: length(GAME_COVER_SIZE_Y * params.scale),
|
||||||
|
|
@ -202,21 +199,21 @@ impl View {
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
position: taffy::Position::Absolute,
|
position: taffy::Position::Absolute,
|
||||||
size: taffy::Size {
|
size: taffy::Size {
|
||||||
width: percent(1.0),
|
width: percent(1.0_f32),
|
||||||
height: percent(1.0),
|
height: percent(1.0_f32),
|
||||||
},
|
},
|
||||||
padding: taffy::Rect::length(2.0),
|
padding: taffy::Rect::length(2.0_f32),
|
||||||
align_items: Some(AlignItems::Center),
|
align_items: Some(AlignItems::CENTER),
|
||||||
justify_content: Some(JustifyContent::Center),
|
justify_content: Some(JustifyContent::CENTER),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let rect_gradient = |color: drawing::Color, color2: drawing::Color| {
|
let rect_gradient = |color: drawing::Color, color2: drawing::Color, round: f32| {
|
||||||
rectangle::WidgetRectangle::create(rectangle::WidgetRectangleParams {
|
rectangle::WidgetRectangle::create(rectangle::WidgetRectangleParams {
|
||||||
color,
|
color: color.into(),
|
||||||
color2,
|
color2: color2.into(),
|
||||||
round: WLength::Units(12.0),
|
round: WLength::Units(round),
|
||||||
gradient: GradientMode::Vertical,
|
gradient: GradientMode::Vertical,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
|
@ -226,7 +223,7 @@ impl View {
|
||||||
position: taffy::Position::Absolute,
|
position: taffy::Position::Absolute,
|
||||||
align_self: Some(align_self),
|
align_self: Some(align_self),
|
||||||
size: taffy::Size {
|
size: taffy::Size {
|
||||||
width: percent(1.0),
|
width: percent(1.0_f32),
|
||||||
height: percent(height),
|
height: percent(height),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -237,9 +234,10 @@ impl View {
|
||||||
widget_button.id,
|
widget_button.id,
|
||||||
rect_gradient(
|
rect_gradient(
|
||||||
drawing::Color::new(1.0, 1.0, 1.0, 0.2),
|
drawing::Color::new(1.0, 1.0, 1.0, 0.2),
|
||||||
drawing::Color::new(1.0, 1.0, 1.0, 0.02),
|
drawing::Color::new(1.0, 1.0, 1.0, 0.01),
|
||||||
|
8.0,
|
||||||
),
|
),
|
||||||
rect_gradient_style(taffy::AlignSelf::Baseline, 0.05),
|
rect_gradient_style(taffy::AlignSelf::BASELINE, 0.05),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// not optimal, this forces us to create a new pass for every created cover art just to overlay various rectangles at the top of the image cover art
|
// not optimal, this forces us to create a new pass for every created cover art just to overlay various rectangles at the top of the image cover art
|
||||||
|
|
@ -251,8 +249,9 @@ impl View {
|
||||||
rect_gradient(
|
rect_gradient(
|
||||||
drawing::Color::new(1.0, 1.0, 1.0, 0.15),
|
drawing::Color::new(1.0, 1.0, 1.0, 0.15),
|
||||||
drawing::Color::new(1.0, 1.0, 1.0, 0.0),
|
drawing::Color::new(1.0, 1.0, 1.0, 0.0),
|
||||||
|
8.0,
|
||||||
),
|
),
|
||||||
rect_gradient_style(taffy::AlignSelf::Baseline, 0.5),
|
rect_gradient_style(taffy::AlignSelf::BASELINE, 0.5),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// bottom black gradient
|
// bottom black gradient
|
||||||
|
|
@ -261,8 +260,9 @@ impl View {
|
||||||
rect_gradient(
|
rect_gradient(
|
||||||
drawing::Color::new(0.0, 0.0, 0.0, 0.0),
|
drawing::Color::new(0.0, 0.0, 0.0, 0.0),
|
||||||
drawing::Color::new(0.0, 0.0, 0.0, 0.25),
|
drawing::Color::new(0.0, 0.0, 0.0, 0.25),
|
||||||
|
8.0,
|
||||||
),
|
),
|
||||||
rect_gradient_style(taffy::AlignSelf::End, 0.5),
|
rect_gradient_style(taffy::AlignSelf::END, 0.5),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// bottom shadow
|
// bottom shadow
|
||||||
|
|
@ -271,8 +271,9 @@ impl View {
|
||||||
rect_gradient(
|
rect_gradient(
|
||||||
drawing::Color::new(0.0, 0.0, 0.0, 0.1),
|
drawing::Color::new(0.0, 0.0, 0.0, 0.1),
|
||||||
drawing::Color::new(0.0, 0.0, 0.0, 0.9),
|
drawing::Color::new(0.0, 0.0, 0.0, 0.9),
|
||||||
|
8.0,
|
||||||
),
|
),
|
||||||
rect_gradient_style(taffy::AlignSelf::End, 0.05),
|
rect_gradient_style(taffy::AlignSelf::END, 0.05),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let id_loading = wgui_simple::create_loading(wgui_simple::CreateLoadingParams {
|
let id_loading = wgui_simple::create_loading(wgui_simple::CreateLoadingParams {
|
||||||
|
|
@ -285,7 +286,6 @@ impl View {
|
||||||
params
|
params
|
||||||
.executor
|
.executor
|
||||||
.spawn(View::request_cover_image(
|
.spawn(View::request_cover_image(
|
||||||
params.executor.clone(),
|
|
||||||
params.manifest.clone(),
|
params.manifest.clone(),
|
||||||
Box::new(params.on_loaded),
|
Box::new(params.on_loaded),
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,8 @@ pub struct View {
|
||||||
|
|
||||||
impl ViewTrait for View {
|
impl ViewTrait for View {
|
||||||
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||||
loop {
|
while !self.tasks.is_empty() {
|
||||||
let tasks = self.tasks.drain();
|
for task in self.tasks.drain() {
|
||||||
if tasks.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for task in tasks {
|
|
||||||
match task {
|
match task {
|
||||||
Task::FillAppDetails(details) => self.action_fill_app_details(par.layout, details)?,
|
Task::FillAppDetails(details) => self.action_fill_app_details(par.layout, details)?,
|
||||||
Task::Launch => self.action_launch(),
|
Task::Launch => self.action_launch(),
|
||||||
|
|
@ -75,8 +71,8 @@ impl ViewTrait for View {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
async fn fetch_details(executor: AsyncExecutor, tasks: Tasks<Task>, app_id: AppID) {
|
async fn fetch_details(tasks: Tasks<Task>, app_id: AppID) {
|
||||||
let Some(details) = cached_fetcher::get_app_details_json(executor, app_id).await else {
|
let Some(details) = cached_fetcher::get_app_details_json(app_id).await else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -103,7 +99,7 @@ impl View {
|
||||||
let tasks = Tasks::new();
|
let tasks = Tasks::new();
|
||||||
|
|
||||||
// fetch details from the web
|
// fetch details from the web
|
||||||
let fut = View::fetch_details(params.executor.clone(), tasks.clone(), params.manifest.app_id.clone());
|
let fut = View::fetch_details(tasks.clone(), params.manifest.app_id.clone());
|
||||||
params.executor.spawn(fut).detach();
|
params.executor.spawn(fut).detach();
|
||||||
|
|
||||||
let id_cover_art_parent = state.get_widget_id("cover_art_parent")?;
|
let id_cover_art_parent = state.get_widget_id("cover_art_parent")?;
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,8 @@ pub struct View {
|
||||||
|
|
||||||
impl ViewTrait for View {
|
impl ViewTrait for View {
|
||||||
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||||
loop {
|
while !self.tasks.is_empty() {
|
||||||
let tasks = self.tasks.drain();
|
for task in self.tasks.drain() {
|
||||||
if tasks.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for task in tasks {
|
|
||||||
match task {
|
match task {
|
||||||
Task::LoadManifests => self.load_manifests(),
|
Task::LoadManifests => self.load_manifests(),
|
||||||
Task::FillPage(page_idx) => self.fill_page(par.layout, par.executor, page_idx)?,
|
Task::FillPage(page_idx) => self.fill_page(par.layout, par.executor, page_idx)?,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use wlx_common::{async_executor::AsyncExecutor, config::GeneralConfig, dash_inte
|
||||||
pub mod app_launcher;
|
pub mod app_launcher;
|
||||||
pub mod audio_settings;
|
pub mod audio_settings;
|
||||||
pub mod bindings;
|
pub mod bindings;
|
||||||
|
pub mod color_palettes;
|
||||||
pub mod dialog_box;
|
pub mod dialog_box;
|
||||||
pub mod download_file;
|
pub mod download_file;
|
||||||
pub mod game_cover;
|
pub mod game_cover;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use crate::{
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
|
color::WguiColorName,
|
||||||
components::button::ComponentButton,
|
components::button::ComponentButton,
|
||||||
drawing::Color,
|
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
|
|
@ -86,7 +86,7 @@ fn mount_resolution_button(
|
||||||
let button = data.fetch_component_as::<ComponentButton>("button")?;
|
let button = data.fetch_component_as::<ComponentButton>("button")?;
|
||||||
|
|
||||||
if already_downloaded {
|
if already_downloaded {
|
||||||
button.set_color(&mut layout.common(), Color::new(0.0, 0.4, 0.0, 1.0)); // green
|
button.set_color(&mut layout.common(), WguiColorName::Tertiary.into()); // green
|
||||||
}
|
}
|
||||||
tasks.handle_button(&button, Task::ResolutionClicked(res));
|
tasks.handle_button(&button, Task::ResolutionClicked(res));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,8 @@ impl ViewTrait for View {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
async fn skymap_catalog_request_wrapper(tasks: Tasks<Task>, executor: AsyncExecutor) {
|
async fn skymap_catalog_request_wrapper(tasks: Tasks<Task>) {
|
||||||
let res = networking::skymap_catalog::request_catalog(&executor).await;
|
let res = networking::skymap_catalog::request_catalog().await;
|
||||||
tasks.push(Task::SetSkymapCatalog(Rc::new(res)))
|
tasks.push(Task::SetSkymapCatalog(Rc::new(res)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,7 +131,7 @@ impl View {
|
||||||
with_text: true,
|
with_text: true,
|
||||||
})?;
|
})?;
|
||||||
let tasks = Tasks::<Task>::new();
|
let tasks = Tasks::<Task>::new();
|
||||||
let fut = View::skymap_catalog_request_wrapper(tasks.clone(), par.executor.clone());
|
let fut = View::skymap_catalog_request_wrapper(tasks.clone());
|
||||||
par.executor.spawn(fut).detach();
|
par.executor.spawn(fut).detach();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id_parent: par.parent_id,
|
id_parent: par.parent_id,
|
||||||
|
|
@ -147,15 +147,10 @@ impl View {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn request_skymap_preview(
|
async fn request_skymap_preview(globals: WguiGlobals, entry: SkymapCatalogEntry, tasks: Tasks<Task>) {
|
||||||
globals: WguiGlobals,
|
|
||||||
executor: AsyncExecutor,
|
|
||||||
entry: SkymapCatalogEntry,
|
|
||||||
tasks: Tasks<Task>,
|
|
||||||
) {
|
|
||||||
tasks.push(Task::SetSkymapPreview((
|
tasks.push(Task::SetSkymapPreview((
|
||||||
entry.uuid,
|
entry.uuid,
|
||||||
networking::image_fetch::fetch_to_glyph_data(&globals, &executor, &entry.files.get_url_preview())
|
networking::image_fetch::fetch_to_glyph_data(&globals, &entry.files.get_url_preview())
|
||||||
.await
|
.await
|
||||||
.ok(),
|
.ok(),
|
||||||
)));
|
)));
|
||||||
|
|
@ -192,12 +187,7 @@ impl View {
|
||||||
let id_list = parser_state.fetch_widget(&layout.state, "list")?.id;
|
let id_list = parser_state.fetch_widget(&layout.state, "list")?.id;
|
||||||
|
|
||||||
for entry in &catalog.entries {
|
for entry in &catalog.entries {
|
||||||
let task = View::request_skymap_preview(
|
let task = View::request_skymap_preview(self.globals.clone(), entry.clone(), self.tasks.clone());
|
||||||
self.globals.clone(),
|
|
||||||
self.executor.clone(),
|
|
||||||
entry.clone(),
|
|
||||||
self.tasks.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let skymap_uuid = entry.uuid;
|
let skymap_uuid = entry.uuid;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,13 +77,8 @@ impl View {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, layout: &mut Layout, time_ms: u32) -> anyhow::Result<()> {
|
pub fn update(&mut self, layout: &mut Layout, time_ms: u32) -> anyhow::Result<()> {
|
||||||
loop {
|
while !self.tasks.is_empty() {
|
||||||
let tasks = self.tasks.drain();
|
for task in self.tasks.drain() {
|
||||||
if tasks.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for task in tasks {
|
|
||||||
match task {
|
match task {
|
||||||
Task::Refresh => self.refresh(layout)?,
|
Task::Refresh => self.refresh(layout)?,
|
||||||
Task::StopGame(app_id, kill) => self.stop_game(app_id, kill),
|
Task::StopGame(app_id, kill) => self.stop_game(app_id, kill),
|
||||||
|
|
|
||||||
|
|
@ -58,12 +58,8 @@ impl ViewTrait for View {
|
||||||
self.popup_remote_skymap_list.update(par)?;
|
self.popup_remote_skymap_list.update(par)?;
|
||||||
self.popup_dialog_box.update(par)?;
|
self.popup_dialog_box.update(par)?;
|
||||||
|
|
||||||
loop {
|
while !self.tasks.is_empty() {
|
||||||
let tasks = self.tasks.drain();
|
for task in self.tasks.drain() {
|
||||||
if tasks.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for task in tasks {
|
|
||||||
match task {
|
match task {
|
||||||
Task::DownloadSkymaps => {
|
Task::DownloadSkymaps => {
|
||||||
self.download_skymaps(par.executor)?;
|
self.download_skymaps(par.executor)?;
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,6 @@ Glossary:
|
||||||
|
|
||||||
End of glossary.
|
End of glossary.
|
||||||
|
|
||||||
|
Style: These are UI elements in a software, so keep the translations cocise and with an appropriate tone. Don't use polite/formal language. Make sure it sounds natural.
|
||||||
|
|
||||||
You will be given the input in the code blocks which needs to be translated to {TARGET_LANG} language. Write only the result in codeblocks, do not explain. Keep any newlines and other important formatting-required identifiers as-is, in the same state.
|
You will be given the input in the code blocks which needs to be translated to {TARGET_LANG} language. Write only the result in codeblocks, do not explain. Keep any newlines and other important formatting-required identifiers as-is, in the same state.
|
||||||
|
|
|
||||||
|
|
@ -97,44 +97,141 @@ interface Template {
|
||||||
examples: Example[];
|
examples: Example[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CsvEntry {
|
||||||
|
key: string;
|
||||||
|
english: string;
|
||||||
|
context: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_csv_line(line: string): [string, string, string] {
|
||||||
|
const result: string[] = [];
|
||||||
|
let current = "";
|
||||||
|
let inQuotes = false;
|
||||||
|
for (let i = 0; i < line.length; i++) {
|
||||||
|
const ch = line[i]!;
|
||||||
|
if (ch === '"') {
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
} else if (ch === "," && !inQuotes) {
|
||||||
|
result.push(current.trim());
|
||||||
|
current = "";
|
||||||
|
} else {
|
||||||
|
current += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(current.trim());
|
||||||
|
return [result[0]!, result[1]!, result[2] ?? ""];
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_csv(text: string): CsvEntry[] {
|
||||||
|
const lines: string[] = [];
|
||||||
|
let current = "";
|
||||||
|
let inQuotes = false;
|
||||||
|
for (const line of text.split("\n")) {
|
||||||
|
const wasInQuotes = inQuotes;
|
||||||
|
for (const ch of line) {
|
||||||
|
if (ch === '"') {
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wasInQuotes) {
|
||||||
|
current += line + "\n";
|
||||||
|
} else {
|
||||||
|
if (current) lines.push(current);
|
||||||
|
current = line + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current) lines.push(current);
|
||||||
|
return lines
|
||||||
|
.filter((l) => l.trim())
|
||||||
|
.map(parse_csv_line)
|
||||||
|
.map(([key, english, context]) => ({
|
||||||
|
key,
|
||||||
|
english,
|
||||||
|
context,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function csv_to_json(entries: CsvEntry[]): any {
|
||||||
|
const result: any = {};
|
||||||
|
for (const entry of entries) {
|
||||||
|
set_i18n_key(result, entry.key, entry.english);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_nested_value(obj: any, key: string): string | undefined {
|
||||||
|
const parts = key.split(".");
|
||||||
|
let level = obj;
|
||||||
|
for (const part of parts) {
|
||||||
|
if (!level || typeof level !== "object") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
level = level[part];
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolve_variables(
|
||||||
|
text: string,
|
||||||
|
translated_json: any,
|
||||||
|
all_entries: CsvEntry[],
|
||||||
|
): string {
|
||||||
|
return text.replace(/\$\{([^}]+)\}/g, (_, key) => {
|
||||||
|
const val = get_nested_value(translated_json, key);
|
||||||
|
if (val !== undefined) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
const entry = all_entries.find((e) => e.key === key);
|
||||||
|
if (entry !== undefined) {
|
||||||
|
return entry.english;
|
||||||
|
}
|
||||||
|
return `${key}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function gen_prompt(
|
function gen_prompt(
|
||||||
description: string,
|
description: string,
|
||||||
template: Template,
|
template: Template,
|
||||||
key: string,
|
key: string,
|
||||||
english_translation: string,
|
english_translation: string,
|
||||||
|
context: string,
|
||||||
) {
|
) {
|
||||||
let num = 1;
|
for (let num = 1; num <= template.examples.length; num++) {
|
||||||
for (const example of template.examples) {
|
const example = template.examples[num - 1]!;
|
||||||
description += "\nExample " + num + ":\n\n";
|
|
||||||
description +=
|
description +=
|
||||||
"Translate key `" +
|
`\nExample ${num}:\n\n` +
|
||||||
example.key +
|
`Translate key \`${example.key}\` from English to ${template.full_name}:\n\n` +
|
||||||
"` from English to " +
|
"```\n" +
|
||||||
template.full_name +
|
example.en +
|
||||||
":\n\n";
|
"\n```\n\n" +
|
||||||
description += "```\n";
|
"Result:\n\n```\n" +
|
||||||
description += example.en + "\n";
|
example.translated +
|
||||||
description += "```\n\n";
|
"\n```\n";
|
||||||
description += "Result:\n\n";
|
|
||||||
description += "```\n";
|
|
||||||
description += example.translated + "\n";
|
|
||||||
description += "```\n";
|
|
||||||
num += 1;
|
|
||||||
}
|
}
|
||||||
description += "\nEnd of examples.\n\n";
|
|
||||||
description +=
|
description +=
|
||||||
"Translate key `" +
|
`\nEnd of examples.\n\n` +
|
||||||
key +
|
`Context: ${context}\n\n` +
|
||||||
"` from English to " +
|
`Translate key \`${key}\` from English to ${template.full_name}:\n\n` +
|
||||||
template.full_name +
|
"```\n" +
|
||||||
":\n\n";
|
english_translation +
|
||||||
description += "```\n";
|
"\n```\n";
|
||||||
description += english_translation + "\n";
|
|
||||||
description += "```\n";
|
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
|
const csv_text = (await fsp.readFile(lang_path + "/en.csv", "utf-8")) as any;
|
||||||
|
const csv_entries = parse_csv(csv_text);
|
||||||
|
const orig_english_json = csv_to_json(csv_entries);
|
||||||
|
|
||||||
|
if (template_name === "en") {
|
||||||
|
await fsp.writeFile(
|
||||||
|
lang_path + "/en.json",
|
||||||
|
JSON.stringify(orig_english_json, undefined, "\t"),
|
||||||
|
);
|
||||||
|
console.log("Translation en copied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const template = JSON.parse(
|
const template = JSON.parse(
|
||||||
await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8"),
|
await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8"),
|
||||||
) as Template;
|
) as Template;
|
||||||
|
|
@ -148,60 +245,49 @@ async function run() {
|
||||||
template.full_name,
|
template.full_name,
|
||||||
);
|
);
|
||||||
|
|
||||||
const orig_english_json = JSON.parse(
|
let llm_translated_json: any = {};
|
||||||
(await fsp.readFile(lang_path + "/en.json")) as any,
|
|
||||||
);
|
|
||||||
|
|
||||||
let orig_translated_json = {};
|
|
||||||
try {
|
|
||||||
orig_translated_json = JSON.parse(
|
|
||||||
(
|
|
||||||
await fsp.readFile(lang_path + "/" + template_name + ".json")
|
|
||||||
).toString(),
|
|
||||||
);
|
|
||||||
} catch (_e) {}
|
|
||||||
|
|
||||||
let llm_translated_json = {};
|
|
||||||
const translated_json_path = lang_path + "/" + template_name + ".json";
|
const translated_json_path = lang_path + "/" + template_name + ".json";
|
||||||
if (await fsp.exists(translated_json_path)) {
|
try {
|
||||||
console.log("Loading file", translated_json_path);
|
console.log("Loading file", translated_json_path);
|
||||||
llm_translated_json = JSON.parse(
|
llm_translated_json = JSON.parse(
|
||||||
(await fsp.readFile(translated_json_path)).toString(),
|
(await fsp.readFile(translated_json_path)).toString(),
|
||||||
);
|
);
|
||||||
}
|
} catch (_e) {}
|
||||||
|
|
||||||
let total_count = 0;
|
|
||||||
await loop_object(orig_english_json, "", async () => {
|
|
||||||
total_count += 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
await loop_object(llm_translated_json, "", async (key, _) => {
|
await loop_object(llm_translated_json, "", async (key, _) => {
|
||||||
if (!key_exists(orig_english_json, key)) {
|
if (!key_exists(orig_english_json, key)) {
|
||||||
console.log("Removing key", key);
|
console.log("Removing key", key);
|
||||||
set_i18n_key(llm_translated_json, key, undefined);
|
set_i18n_key(llm_translated_json, key, undefined);
|
||||||
fsp.writeFile(
|
await fsp.writeFile(
|
||||||
translated_json_path,
|
translated_json_path,
|
||||||
JSON.stringify(llm_translated_json, undefined, "\t"),
|
JSON.stringify(llm_translated_json, undefined, "\t"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await loop_object(orig_english_json, "", async (key, english_translation) => {
|
for (const entry of csv_entries) {
|
||||||
if (key_exists(orig_translated_json, key)) {
|
const key = entry.key;
|
||||||
return;
|
const english_translation = entry.english;
|
||||||
}
|
const context = entry.context;
|
||||||
|
|
||||||
if (key_exists(llm_translated_json, key)) {
|
if (key_exists(llm_translated_json, key)) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Translating", key, "...");
|
console.log("Translating", key, "...");
|
||||||
|
|
||||||
|
const resolved_context = resolve_variables(
|
||||||
|
context,
|
||||||
|
llm_translated_json,
|
||||||
|
csv_entries,
|
||||||
|
);
|
||||||
|
|
||||||
const prompt = gen_prompt(
|
const prompt = gen_prompt(
|
||||||
description_txt,
|
description_txt,
|
||||||
template,
|
template,
|
||||||
key,
|
key,
|
||||||
english_translation,
|
english_translation,
|
||||||
|
resolved_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
const response = await fetch(base_url + "/v1/chat/completions", {
|
const response = await fetch(base_url + "/v1/chat/completions", {
|
||||||
|
|
@ -237,11 +323,11 @@ async function run() {
|
||||||
console.log(" >>>", msg);
|
console.log(" >>>", msg);
|
||||||
|
|
||||||
set_i18n_key(llm_translated_json, key, msg[0]);
|
set_i18n_key(llm_translated_json, key, msg[0]);
|
||||||
fsp.writeFile(
|
await fsp.writeFile(
|
||||||
translated_json_path,
|
translated_json_path,
|
||||||
JSON.stringify(llm_translated_json, undefined, "\t"),
|
JSON.stringify(llm_translated_json, undefined, "\t"),
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
console.log("Translation", template_name, "finished");
|
console.log("Translation", template_name, "finished");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ if [ -z "${LLAMA_BASE_URL}" ]; then
|
||||||
export LLAMA_BASE_URL="http://127.0.0.1:8080"
|
export LLAMA_BASE_URL="http://127.0.0.1:8080"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
TEMPLATE="en" bun main.ts
|
||||||
TEMPLATE="pl" bun main.ts
|
TEMPLATE="pl" bun main.ts
|
||||||
TEMPLATE="de" bun main.ts
|
TEMPLATE="de" bun main.ts
|
||||||
TEMPLATE="ja" bun main.ts
|
TEMPLATE="ja" bun main.ts
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,16 @@ authors = ["galister", "oo8dev"]
|
||||||
repository = "https://github.com/wlx-team/wayvr"
|
repository = "https://github.com/wlx-team/wayvr"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
|
||||||
glam = { workspace = true }
|
|
||||||
log = { workspace = true }
|
|
||||||
rust-embed = "8.9.0"
|
|
||||||
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
|
||||||
wgui = { path = "../wgui/" }
|
|
||||||
winit = "0.30.12"
|
|
||||||
vulkano = { workspace = true }
|
|
||||||
vulkano-shaders = { workspace = true }
|
|
||||||
dash-frontend = { path = "../dash-frontend/" }
|
dash-frontend = { path = "../dash-frontend/" }
|
||||||
|
wgui = { path = "../wgui/" }
|
||||||
wlx-common = { path = "../wlx-common" }
|
wlx-common = { path = "../wlx-common" }
|
||||||
|
|
||||||
|
anyhow.workspace = true
|
||||||
|
glam.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
rust-embed.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
vulkano.workspace = true
|
||||||
|
vulkano-shaders.workspace = true
|
||||||
|
winit.workspace = true
|
||||||
|
ureq = "3.3.0"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<layout>
|
|
||||||
<!-- TODO: deprecate this in favor of theme.xml -->
|
|
||||||
<theme>
|
|
||||||
<var key="color_bg" value="#24273a" />
|
|
||||||
<var key="color_bg_active" value="#44475a" />
|
|
||||||
<var key="text_color" value="#dddddd" />
|
|
||||||
</theme>
|
|
||||||
</layout>
|
|
||||||
|
|
@ -10,6 +10,7 @@ use wgui::{
|
||||||
font_config::WguiFontConfig,
|
font_config::WguiFontConfig,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
layout::{Layout, LayoutParams, LayoutUpdateParams},
|
layout::{Layout, LayoutParams, LayoutUpdateParams},
|
||||||
|
palette::WguiColorPalette,
|
||||||
parser::{ParseDocumentParams, ParserState},
|
parser::{ParseDocumentParams, ParserState},
|
||||||
};
|
};
|
||||||
use wlx_common::locale::WayVRLangProvider;
|
use wlx_common::locale::WayVRLangProvider;
|
||||||
|
|
@ -30,12 +31,14 @@ impl TestbedAny {
|
||||||
};
|
};
|
||||||
|
|
||||||
let lang_provider = WayVRLangProvider::default();
|
let lang_provider = WayVRLangProvider::default();
|
||||||
|
let palette_name = std::env::var("PALETTE").unwrap_or_else(|_| "Default".to_string());
|
||||||
|
|
||||||
let globals = WguiGlobals::new(
|
let globals = WguiGlobals::new(
|
||||||
assets,
|
assets,
|
||||||
&lang_provider,
|
&lang_provider,
|
||||||
&WguiFontConfig::default(),
|
&WguiFontConfig::default(),
|
||||||
PathBuf::new(), // cwd
|
PathBuf::new(), // cwd
|
||||||
|
WguiColorPalette::get_builtin(&palette_name),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,13 @@ use std::rc::Rc;
|
||||||
use crate::testbed::{Testbed, TestbedUpdateParams};
|
use crate::testbed::{Testbed, TestbedUpdateParams};
|
||||||
use dash_frontend::frontend::{self, FrontendUpdateParams};
|
use dash_frontend::frontend::{self, FrontendUpdateParams};
|
||||||
use wgui::{layout::Layout, theme::WguiTheme};
|
use wgui::{layout::Layout, theme::WguiTheme};
|
||||||
use wlx_common::{dash_interface_emulated::DashInterfaceEmulated, locale::WayVRLangProvider};
|
use wlx_common::{
|
||||||
|
async_executor::AsyncExecutor, dash_interface_emulated::DashInterfaceEmulated,
|
||||||
|
locale::WayVRLangProvider,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct TestbedDashboard {
|
pub struct TestbedDashboard {
|
||||||
|
executor: AsyncExecutor,
|
||||||
frontend: frontend::Frontend<()>,
|
frontend: frontend::Frontend<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13,6 +17,8 @@ impl TestbedDashboard {
|
||||||
pub fn new() -> anyhow::Result<Self> {
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
let interface = DashInterfaceEmulated::new();
|
let interface = DashInterfaceEmulated::new();
|
||||||
let lang_provider = WayVRLangProvider::default();
|
let lang_provider = WayVRLangProvider::default();
|
||||||
|
let palette_name = std::env::var("PALETTE").unwrap_or_else(|_| "Default".to_string());
|
||||||
|
let executor = wlx_common::async_executor::create_local();
|
||||||
|
|
||||||
let frontend = frontend::Frontend::new(frontend::InitParams {
|
let frontend = frontend::Frontend::new(frontend::InitParams {
|
||||||
interface: Box::new(interface),
|
interface: Box::new(interface),
|
||||||
|
|
@ -20,8 +26,10 @@ impl TestbedDashboard {
|
||||||
has_monado: true,
|
has_monado: true,
|
||||||
lang_provider: &lang_provider,
|
lang_provider: &lang_provider,
|
||||||
theme: Rc::new(WguiTheme::default()),
|
theme: Rc::new(WguiTheme::default()),
|
||||||
|
color_palette: &palette_name,
|
||||||
|
executor: executor.clone(),
|
||||||
})?;
|
})?;
|
||||||
Ok(Self { frontend })
|
Ok(Self { frontend, executor })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,6 +44,8 @@ impl Testbed for TestbedDashboard {
|
||||||
self
|
self
|
||||||
.frontend
|
.frontend
|
||||||
.process_update(res, params.audio_system, params.audio_sample_player)?;
|
.process_update(res, params.audio_system, params.audio_sample_player)?;
|
||||||
|
|
||||||
|
while self.executor.try_tick() {}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use wgui::{
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, LayoutParams, LayoutUpdateParams, Widget},
|
layout::{Layout, LayoutParams, LayoutUpdateParams, Widget},
|
||||||
|
palette::WguiColorPalette,
|
||||||
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
|
||||||
taffy::{self, prelude::length},
|
taffy::{self, prelude::length},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
|
|
@ -86,12 +87,14 @@ impl TestbedGeneric {
|
||||||
|
|
||||||
pub fn new(assets: Box<assets::Asset>) -> anyhow::Result<Self> {
|
pub fn new(assets: Box<assets::Asset>) -> anyhow::Result<Self> {
|
||||||
let lang_provider = WayVRLangProvider::default();
|
let lang_provider = WayVRLangProvider::default();
|
||||||
|
let palette_name = std::env::var("PALETTE").unwrap_or_else(|_| "Default".to_string());
|
||||||
|
|
||||||
let globals = WguiGlobals::new(
|
let globals = WguiGlobals::new(
|
||||||
assets,
|
assets,
|
||||||
&lang_provider,
|
&lang_provider,
|
||||||
&WguiFontConfig::default(),
|
&WguiFontConfig::default(),
|
||||||
PathBuf::new(), // cwd
|
PathBuf::new(), // cwd
|
||||||
|
WguiColorPalette::get_builtin(&palette_name),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let extra = ParseDocumentExtra {
|
let extra = ParseDocumentExtra {
|
||||||
|
|
@ -116,9 +119,9 @@ impl TestbedGeneric {
|
||||||
color = color.mult_rgb(mult_f32);
|
color = color.mult_rgb(mult_f32);
|
||||||
|
|
||||||
let mut rect = par.get_widget_as::<WidgetRectangle>().unwrap();
|
let mut rect = par.get_widget_as::<WidgetRectangle>().unwrap();
|
||||||
rect.params.color = color;
|
rect.params.color = color.into();
|
||||||
})),
|
})),
|
||||||
dev_mode: false,
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let (layout, parser_state) = wgui::parser::new_layout_from_assets(
|
let (layout, parser_state) = wgui::parser::new_layout_from_assets(
|
||||||
|
|
@ -234,8 +237,8 @@ impl TestbedGeneric {
|
||||||
WidgetDiv::create(),
|
WidgetDiv::create(),
|
||||||
taffy::Style {
|
taffy::Style {
|
||||||
size: taffy::Size {
|
size: taffy::Size {
|
||||||
width: length(128.0),
|
width: length(128.0_f32),
|
||||||
height: length(64.0),
|
height: length(64.0_f32),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ pub fn init_window(
|
||||||
let event_loop = EventLoop::new().unwrap(); // want panic
|
let event_loop = EventLoop::new().unwrap(); // want panic
|
||||||
let mut vk_instance_extensions = Surface::required_extensions(&event_loop).unwrap();
|
let mut vk_instance_extensions = Surface::required_extensions(&event_loop).unwrap();
|
||||||
vk_instance_extensions.khr_get_physical_device_properties2 = true;
|
vk_instance_extensions.khr_get_physical_device_properties2 = true;
|
||||||
log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions);
|
log::debug!("Instance exts for runtime: {:?}", vk_instance_extensions);
|
||||||
|
|
||||||
let instance = Instance::new(
|
let instance = Instance::new(
|
||||||
get_vulkan_library().clone(),
|
get_vulkan_library().clone(),
|
||||||
|
|
@ -57,7 +57,7 @@ pub fn init_window(
|
||||||
let mut device_extensions = DeviceExtensions::empty();
|
let mut device_extensions = DeviceExtensions::empty();
|
||||||
device_extensions.khr_swapchain = true;
|
device_extensions.khr_swapchain = true;
|
||||||
|
|
||||||
log::debug!("Device exts for app: {:?}", &device_extensions);
|
log::debug!("Device exts for app: {:?}", device_extensions);
|
||||||
|
|
||||||
let (physical_device, mut my_extensions, queue_families) = instance
|
let (physical_device, mut my_extensions, queue_families) = instance
|
||||||
.enumerate_physical_devices()?
|
.enumerate_physical_devices()?
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,20 @@ authors = ["galister", "oo8dev"]
|
||||||
repository = "https://github.com/wlx-team/wayvr"
|
repository = "https://github.com/wlx-team/wayvr"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.93"
|
anyhow.workspace = true
|
||||||
|
async-channel.workspace = true
|
||||||
|
async-io.workspace = true
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
log = "0.4.22"
|
interprocess.workspace = true
|
||||||
|
log.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
smallvec = "1.13.2"
|
slotmap.workspace = true
|
||||||
|
smallvec.workspace = true
|
||||||
|
|
||||||
# client-only deps
|
# client-only deps
|
||||||
interprocess = { version = "2.2.2", features = ["tokio"], optional = true }
|
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
tokio = { version = "1.43.1", features = ["macros"], optional = true }
|
smol = { workspace = true, optional = true }
|
||||||
tokio-util = { version = "0.7.13", optional = true }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["client"]
|
default = ["client"]
|
||||||
client = ["dep:interprocess", "dep:tokio", "dep:tokio-util"]
|
client = ["dep:smol"]
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
use interprocess::local_socket::{
|
use interprocess::local_socket::{self, ToNsName};
|
||||||
self, GenericNamespaced,
|
|
||||||
tokio::{Stream, prelude::*},
|
|
||||||
};
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use slotmap::DenseSlotMap;
|
||||||
|
use slotmap::new_key_type;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use smol::io::AsyncReadExt;
|
||||||
|
use smol::io::AsyncWriteExt;
|
||||||
|
use smol::lock::Mutex;
|
||||||
|
use std::os::unix::net::UnixStream as StdUnixStream;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use tokio::{
|
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
|
||||||
sync::Mutex,
|
|
||||||
};
|
|
||||||
use tokio_util::sync::CancellationToken;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gen_id,
|
|
||||||
ipc::{self, Serial},
|
ipc::{self, Serial},
|
||||||
packet_client::{self, HandsfreeParams, PacketClient},
|
packet_client::{self, HandsfreeParams, PacketClient},
|
||||||
packet_server::{self, PacketServer},
|
packet_server::{self, PacketServer},
|
||||||
|
|
@ -26,28 +23,22 @@ pub struct QueuedPacket {
|
||||||
packet: Option<PacketServer>,
|
packet: Option<PacketServer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_id!(
|
new_key_type! {
|
||||||
QueuedPacketVec,
|
pub struct QueuedPacketHandle;
|
||||||
QueuedPacket,
|
}
|
||||||
QueuedPacketCell,
|
|
||||||
QueuedPacketHandle
|
|
||||||
);
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Clone)]
|
#[derive(Debug, Serialize, Clone)]
|
||||||
pub struct AuthInfo {
|
pub struct AuthInfo {
|
||||||
pub runtime: String,
|
pub runtime: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignalFunc = Box<dyn FnMut(&packet_server::PacketServer) -> bool + Send>;
|
|
||||||
|
|
||||||
pub struct WayVRClient {
|
pub struct WayVRClient {
|
||||||
receiver: ReceiverMutex,
|
receiver: ReceiverMutex,
|
||||||
sender: SenderMutex,
|
sender: SenderMutex,
|
||||||
cancel_token: CancellationToken,
|
cancel_tx: async_channel::Sender<()>,
|
||||||
exiting: bool,
|
exiting: bool,
|
||||||
queued_packets: QueuedPacketVec,
|
queued_packets: DenseSlotMap<QueuedPacketHandle, QueuedPacket>,
|
||||||
pub auth: Option<AuthInfo>, // Some if authenticated
|
pub auth: Option<AuthInfo>,
|
||||||
pub on_signal: Option<SignalFunc>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()> {
|
pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()> {
|
||||||
|
|
@ -67,8 +58,26 @@ pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()
|
||||||
pub type WayVRClientMutex = Arc<Mutex<WayVRClient>>;
|
pub type WayVRClientMutex = Arc<Mutex<WayVRClient>>;
|
||||||
pub type WayVRClientWeak = Weak<Mutex<WayVRClient>>;
|
pub type WayVRClientWeak = Weak<Mutex<WayVRClient>>;
|
||||||
|
|
||||||
type ReceiverMutex = Arc<Mutex<local_socket::tokio::RecvHalf>>;
|
type ReceiverMutex = Arc<Mutex<smol::net::unix::UnixStream>>;
|
||||||
type SenderMutex = Arc<Mutex<local_socket::tokio::SendHalf>>;
|
type SenderMutex = Arc<Mutex<smol::net::unix::UnixStream>>;
|
||||||
|
|
||||||
|
fn interprocess_stream_to_async(
|
||||||
|
stream: local_socket::Stream,
|
||||||
|
) -> anyhow::Result<smol::net::unix::UnixStream> {
|
||||||
|
use std::os::unix::io::OwnedFd;
|
||||||
|
|
||||||
|
let uds_stream: interprocess::os::unix::uds_local_socket::Stream = match stream {
|
||||||
|
local_socket::Stream::UdSocket(s) => s,
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
_ => anyhow::bail!("Unsupported socket type"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let owned_fd: OwnedFd = uds_stream.into();
|
||||||
|
let std_stream = StdUnixStream::from(owned_fd);
|
||||||
|
|
||||||
|
smol::net::unix::UnixStream::try_from(std_stream)
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to wrap socket for async I/O: {}", e))
|
||||||
|
}
|
||||||
|
|
||||||
async fn client_runner(client: WayVRClientMutex) -> anyhow::Result<()> {
|
async fn client_runner(client: WayVRClientMutex) -> anyhow::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -79,7 +88,7 @@ async fn client_runner(client: WayVRClientMutex) -> anyhow::Result<()> {
|
||||||
type Payload = SmallVec<[u8; 64]>;
|
type Payload = SmallVec<[u8; 64]>;
|
||||||
|
|
||||||
async fn read_payload(
|
async fn read_payload(
|
||||||
conn: &mut local_socket::tokio::RecvHalf,
|
conn: &mut smol::net::unix::UnixStream,
|
||||||
size: u32,
|
size: u32,
|
||||||
) -> anyhow::Result<Payload> {
|
) -> anyhow::Result<Payload> {
|
||||||
let mut payload = Payload::new();
|
let mut payload = Payload::new();
|
||||||
|
|
@ -116,38 +125,33 @@ macro_rules! send_only {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WayVRClient {
|
impl WayVRClient {
|
||||||
pub fn set_signal_handler(&mut self, on_signal: SignalFunc) {
|
|
||||||
self.on_signal = Some(on_signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn new(client_name: &str) -> anyhow::Result<WayVRClientMutex> {
|
pub async fn new(client_name: &str) -> anyhow::Result<WayVRClientMutex> {
|
||||||
let printname = "/tmp/wayvr_ipc.sock";
|
let printname = "/tmp/wayvr_ipc.sock";
|
||||||
let name = printname.to_ns_name::<GenericNamespaced>()?;
|
|
||||||
|
|
||||||
let stream = match Stream::connect(name).await {
|
let name = printname
|
||||||
Ok(c) => c,
|
.to_ns_name::<local_socket::GenericNamespaced>()
|
||||||
Err(e) => {
|
.map_err(|e| anyhow::anyhow!("Failed to create socket name: {}", e))?;
|
||||||
anyhow::bail!("Failed to connect to the WayVR IPC: {}", e)
|
let opts = local_socket::ConnectOptions::new().name(name);
|
||||||
}
|
let ip_stream = opts
|
||||||
};
|
.connect_sync()
|
||||||
let (receiver, sender) = stream.split();
|
.map_err(|e| anyhow::anyhow!("Failed to connect to the WayVR IPC: {}", e))?;
|
||||||
|
|
||||||
let receiver = Arc::new(Mutex::new(receiver));
|
let async_stream = interprocess_stream_to_async(ip_stream)?;
|
||||||
let sender = Arc::new(Mutex::new(sender));
|
let receiver = Arc::new(Mutex::new(async_stream.clone()));
|
||||||
|
let sender = Arc::new(Mutex::new(async_stream));
|
||||||
|
|
||||||
let cancel_token = CancellationToken::new();
|
let (cancel_tx, cancel_rx) = async_channel::bounded(1);
|
||||||
|
|
||||||
let client = Arc::new(Mutex::new(Self {
|
let client = Arc::new(Mutex::new(Self {
|
||||||
receiver,
|
receiver,
|
||||||
sender: sender.clone(),
|
sender: sender.clone(),
|
||||||
|
cancel_tx,
|
||||||
exiting: false,
|
exiting: false,
|
||||||
cancel_token: cancel_token.clone(),
|
queued_packets: Default::default(),
|
||||||
queued_packets: QueuedPacketVec::new(),
|
|
||||||
auth: None,
|
auth: None,
|
||||||
on_signal: None,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
WayVRClient::start_runner(client.clone(), cancel_token);
|
WayVRClient::start_runner(client.clone(), cancel_rx);
|
||||||
|
|
||||||
// Send handshake to the server
|
// Send handshake to the server
|
||||||
send_packet(
|
send_packet(
|
||||||
|
|
@ -163,17 +167,31 @@ impl WayVRClient {
|
||||||
Ok(client)
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_runner(client: WayVRClientMutex, cancel_token: CancellationToken) {
|
fn start_runner(client: WayVRClientMutex, cancel_rx: async_channel::Receiver<()>) {
|
||||||
tokio::spawn(async move {
|
smol::spawn(async move {
|
||||||
tokio::select! {
|
let cancel_fut = async {
|
||||||
_ = cancel_token.cancelled() => {
|
cancel_rx
|
||||||
log::info!("Exiting IPC runner gracefully");
|
.recv()
|
||||||
}
|
.await
|
||||||
e = client_runner(client.clone()) => {
|
.map_err(|_| anyhow::anyhow!("cancelled"))
|
||||||
log::info!("IPC Runner failed: {:?}", e);
|
};
|
||||||
|
|
||||||
|
let result = smol::future::race(client_runner(client.clone()), cancel_fut).await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(()) => {
|
||||||
|
log::info!("IPC Runner completed");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if e.to_string() == "cancelled" {
|
||||||
|
log::info!("Exiting IPC runner gracefully");
|
||||||
|
} else {
|
||||||
|
log::info!("IPC Runner failed: {:?}", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn tick(client_mtx: WayVRClientMutex) -> anyhow::Result<()> {
|
async fn tick(client_mtx: WayVRClientMutex) -> anyhow::Result<()> {
|
||||||
|
|
@ -185,7 +203,9 @@ impl WayVRClient {
|
||||||
// read packet
|
// read packet
|
||||||
let packet = {
|
let packet = {
|
||||||
let mut receiver = receiver.lock().await;
|
let mut receiver = receiver.lock().await;
|
||||||
let packet_size = receiver.read_u32().await?;
|
let mut size_buf = [0u8; 4];
|
||||||
|
receiver.read_exact(&mut size_buf).await?;
|
||||||
|
let packet_size = u32::from_be_bytes(size_buf);
|
||||||
log::trace!("packet size {}", packet_size);
|
log::trace!("packet size {}", packet_size);
|
||||||
if packet_size > 128 * 1024 {
|
if packet_size > 128 * 1024 {
|
||||||
anyhow::bail!("packet size too large (> 128 KiB)");
|
anyhow::bail!("packet size too large (> 128 KiB)");
|
||||||
|
|
@ -223,22 +243,9 @@ impl WayVRClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let PacketServer::WvrStateChanged(_) = &packet
|
|
||||||
&& let Some(on_signal) = &mut client.on_signal
|
|
||||||
&& (*on_signal)(&packet)
|
|
||||||
{
|
|
||||||
// Signal consumed
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// queue packet to read if it contains a serial response
|
// queue packet to read if it contains a serial response
|
||||||
if let Some(serial) = packet.serial() {
|
if let Some(serial) = packet.serial() {
|
||||||
for qpacket in &mut client.queued_packets.vec {
|
for (_, qpacket) in &mut client.queued_packets {
|
||||||
let Some(qpacket) = qpacket else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let qpacket = &mut qpacket.obj;
|
|
||||||
if qpacket.serial != *serial {
|
if qpacket.serial != *serial {
|
||||||
continue; //skip
|
continue; //skip
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +283,7 @@ impl WayVRClient {
|
||||||
// Send packet to the server
|
// Send packet to the server
|
||||||
let queued_packet_handle = {
|
let queued_packet_handle = {
|
||||||
let mut client = client_mtx.lock().await;
|
let mut client = client_mtx.lock().await;
|
||||||
let handle = client.queued_packets.add(QueuedPacket {
|
let handle = client.queued_packets.insert(QueuedPacket {
|
||||||
notifier: notifier.clone(),
|
notifier: notifier.clone(),
|
||||||
packet: None, // will be filled after notify
|
packet: None, // will be filled after notify
|
||||||
serial,
|
serial,
|
||||||
|
|
@ -299,7 +306,7 @@ impl WayVRClient {
|
||||||
|
|
||||||
let cell = client
|
let cell = client
|
||||||
.queued_packets
|
.queued_packets
|
||||||
.get_mut(&queued_packet_handle)
|
.get_mut(queued_packet_handle)
|
||||||
.ok_or(anyhow::anyhow!(
|
.ok_or(anyhow::anyhow!(
|
||||||
"missing packet cell, this shouldn't happen"
|
"missing packet cell, this shouldn't happen"
|
||||||
))?;
|
))?;
|
||||||
|
|
@ -308,7 +315,7 @@ impl WayVRClient {
|
||||||
anyhow::bail!("packet is None, this shouldn't happen");
|
anyhow::bail!("packet is None, this shouldn't happen");
|
||||||
};
|
};
|
||||||
|
|
||||||
client.queued_packets.remove(&queued_packet_handle);
|
client.queued_packets.remove(queued_packet_handle);
|
||||||
|
|
||||||
Ok(packet)
|
Ok(packet)
|
||||||
}
|
}
|
||||||
|
|
@ -430,6 +437,11 @@ impl WayVRClient {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn fn_wvr_input_capture(client: WayVRClientMutex, grab: bool) -> anyhow::Result<()> {
|
||||||
|
send_only!(client, &PacketClient::WvrInputCapture(grab));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn fn_wlx_modify_panel(
|
pub async fn fn_wlx_modify_panel(
|
||||||
client: WayVRClientMutex,
|
client: WayVRClientMutex,
|
||||||
params: packet_client::WlxModifyPanelParams,
|
params: packet_client::WlxModifyPanelParams,
|
||||||
|
|
@ -442,6 +454,6 @@ impl WayVRClient {
|
||||||
impl Drop for WayVRClient {
|
impl Drop for WayVRClient {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.exiting = true;
|
self.exiting = true;
|
||||||
self.cancel_token.cancel();
|
let _ = self.cancel_tx.try_send(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue