mirror of
https://github.com/wayvr-org/wayvr.git
synced 2026-10-28 19:04:51 +01:00
Compare commits
91
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4229d5cb61 | ||
|
|
abafddefd8 | ||
|
|
9b1fc2774a | ||
|
|
c539ff6a90 | ||
|
|
f94c0c4ace | ||
|
|
5f4c97794c | ||
|
|
d9288a877c | ||
|
|
dff4b0067a | ||
|
|
adf852971f | ||
|
|
074d2de7aa | ||
|
|
e8d9a35714 | ||
|
|
36f9fab5c6 | ||
|
|
058792fc8e | ||
|
|
ef934e0b02 | ||
|
|
c42e992a62 | ||
|
|
41d7a0b3d2 | ||
|
|
471e4be946 | ||
|
|
26afa57fe3 | ||
|
|
d120617abe | ||
|
|
351b24533c | ||
|
|
09ed96542f | ||
|
|
9b89622ff9 | ||
|
|
346c6391ef | ||
|
|
e850c2c8b6 | ||
|
|
5360697828 | ||
|
|
3a869e3c35 | ||
|
|
b3ac55474f | ||
|
|
a4986a3d9f | ||
|
|
f3f7d97ed6 | ||
|
|
10857739a4 | ||
|
|
42e9deb54c | ||
|
|
d6515b3c2a | ||
|
|
a101c79892 | ||
|
|
82565e975f | ||
|
|
959f66b271 | ||
|
|
745728d90d | ||
|
|
68944184de | ||
|
|
4590371a4c | ||
|
|
d1255e5f71 | ||
|
|
537f2f5397 | ||
|
|
77730432b1 | ||
|
|
fd3e9069e4 | ||
|
|
2226d95834 | ||
|
|
a0d36d7257 | ||
|
|
38382275ec | ||
|
|
5517c3a809 | ||
|
|
f0d96802ba | ||
|
|
3f43003a0b | ||
|
|
28842d6d69 | ||
|
|
573bd5da53 | ||
|
|
da3b19a495 | ||
|
|
ad0d1aa8a2 | ||
|
|
b85976bdf0 | ||
|
|
2ea97e88bb | ||
|
|
b7b93131c9 | ||
|
|
e7c07c7789 | ||
|
|
0a158c102c | ||
|
|
11a5c8305b | ||
|
|
d5f0306aab | ||
|
|
6d6e7033ac | ||
|
|
16bc4383b5 | ||
|
|
0e6526836e | ||
|
|
2e8d1589f5 | ||
|
|
54713b95f4 | ||
|
|
6f761a99dc | ||
|
|
c87bcee358 | ||
|
|
0eab390702 | ||
|
|
9dcdf852c7 | ||
|
|
b3261dbe4f | ||
|
|
329a89ca08 | ||
|
|
c284162068 | ||
|
|
f2beabd39a | ||
|
|
126120e52e | ||
|
|
e986c3591e | ||
|
|
a0f096b9dc | ||
|
|
7b95f01ff4 | ||
|
|
d9cc73be8b | ||
|
|
548ea36a84 | ||
|
|
d4a5d4c81f | ||
|
|
443bc01361 | ||
|
|
9b9d1b9f8a | ||
|
|
40811f219e | ||
|
|
a244c90d05 | ||
|
|
f0a1b82db5 | ||
|
|
b45c68cb59 | ||
|
|
234c4a4021 | ||
|
|
10e54728fa | ||
|
|
e4daef209b | ||
|
|
d318831ecc | ||
|
|
48be76c443 | ||
|
|
9d3546b0c4 |
No files matched your search
@@ -9,7 +9,9 @@ assignees: ''
|
||||
|
||||
## Description
|
||||
<!--
|
||||
If this is a regression, please mention which version was working previously.
|
||||
*** Do NOT use AI to generate a bug report! ***
|
||||
Simply write down what's wrong and maybe provide screenshots or a video.
|
||||
If this has worked before, please mention which version was last working.
|
||||
-->
|
||||
|
||||
## System Info
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
name: Build AppImage
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
@@ -12,10 +13,17 @@ env:
|
||||
CARGO_TERM_COLOR: always
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
RUSTC_WRAPPER: "sccache"
|
||||
|
||||
|
||||
jobs:
|
||||
build_appimage:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-24.04
|
||||
arch: x86_64
|
||||
- runner: ubuntu-24.04-arm
|
||||
arch: aarch64
|
||||
runs-on: ${{ matrix.runner }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./wayvr
|
||||
@@ -38,5 +46,10 @@ jobs:
|
||||
- name: Upload AppImage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WayVR-${{ github.ref_name }}-x86_64.AppImage
|
||||
path: ./wayvr/WayVR-x86_64.AppImage
|
||||
name: WayVR-${{ github.ref_name }}-${{ matrix.arch }}.AppImage
|
||||
path: ./wayvr/WayVR-${{ matrix.arch }}.AppImage
|
||||
- name: Upload AppImage zsync
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WayVR-${{ github.ref_name }}-${{ matrix.arch }}.AppImage.zsync
|
||||
path: ./wayvr/WayVR-${{ matrix.arch }}.AppImage.zsync
|
||||
@@ -83,6 +83,16 @@ jobs:
|
||||
asset_name: WayVR-${{ github.ref_name }}-x86_64.AppImage
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload AppImage zsync
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_KEY }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./wayvr/WayVR-x86_64.AppImage.zsync
|
||||
asset_name: WayVR-${{ github.ref_name }}-x86_64.AppImage.zsync
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload vendor tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
sudo apt install \
|
||||
sudo apt-get install -y \
|
||||
xwayland \
|
||||
libxcb1-dev \
|
||||
libxcb-cursor-dev \
|
||||
@@ -11,7 +12,7 @@ git clone https://github.com/Supreeeme/xwayland-satellite.git
|
||||
cd xwayland-satellite
|
||||
|
||||
cargo build --release
|
||||
chmod +x ../target/release/xwayland-satellite
|
||||
chmod +x target/release/xwayland-satellite
|
||||
cd ..
|
||||
|
||||
cp xwayland-satellite/target/release/xwayland-satellite ${APPDIR}/usr/bin
|
||||
cp xwayland-satellite/target/release/xwayland-satellite "${APPDIR}/usr/bin"
|
||||
@@ -1,4 +1,6 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
cargo build --release
|
||||
chmod +x ../target/release/wayvr
|
||||
cp ../target/release/wayvr ${APPDIR}/usr/bin
|
||||
cp ../target/release/wayvr "${APPDIR}/usr/bin"
|
||||
@@ -1,4 +1,35 @@
|
||||
#!/bin/sh
|
||||
export VERSION=$GITHUB_REF_NAME
|
||||
./linuxdeploy-x86_64.AppImage -dwayvr.desktop -iwayvr.png --appdir=${APPDIR} --output appimage --exclude-library '*libpipewire*'
|
||||
mv WayVR-$VERSION-x86_64.AppImage WayVR-x86_64.AppImage
|
||||
set -eu
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64)
|
||||
APPIMAGE_ARCH=x86_64
|
||||
;;
|
||||
aarch64|arm64)
|
||||
APPIMAGE_ARCH=aarch64
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: $(uname -m)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
LINUXDEPLOY="linuxdeploy-${APPIMAGE_ARCH}.AppImage"
|
||||
VERSION="${GITHUB_REF_NAME:-dev}"
|
||||
export VERSION
|
||||
export LDAI_UPDATE_INFORMATION="gh-releases-zsync|wayvr-org|wayvr|latest|WayVR-*-${APPIMAGE_ARCH}.AppImage.zsync"
|
||||
|
||||
echo "Packaging AppImage for ${APPIMAGE_ARCH}"
|
||||
|
||||
# linuxdeploy doesn't like multiple -d's being passed
|
||||
install -Dm 0644 wayvr-headless.desktop "${APPDIR}/usr/share/applications/wayvr-headless.desktop"
|
||||
|
||||
"./${LINUXDEPLOY}" \
|
||||
-dwayvr.desktop \
|
||||
-iwayvr.png \
|
||||
--appdir="${APPDIR}" \
|
||||
--output appimage \
|
||||
--exclude-library '*libpipewire*'
|
||||
|
||||
mv "WayVR-${VERSION}-${APPIMAGE_ARCH}.AppImage" "WayVR-${APPIMAGE_ARCH}.AppImage"
|
||||
mv "WayVR-${VERSION}-${APPIMAGE_ARCH}.AppImage.zsync" "WayVR-${APPIMAGE_ARCH}.AppImage.zsync"
|
||||
@@ -1,17 +1,39 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64)
|
||||
APPIMAGE_ARCH=x86_64
|
||||
;;
|
||||
aarch64|arm64)
|
||||
APPIMAGE_ARCH=aarch64
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: $(uname -m)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
LINUXDEPLOY="linuxdeploy-${APPIMAGE_ARCH}.AppImage"
|
||||
|
||||
echo "Preparing AppImage environment for ${APPIMAGE_ARCH}"
|
||||
|
||||
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 \
|
||||
libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1t64 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
|
||||
|
||||
if [ "$APPDIR" != "" ]; then
|
||||
test -f linuxdeploy-x86_64.AppImage || wget -q "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
||||
chmod +x linuxdeploy-x86_64.AppImage
|
||||
if [ -n "${APPDIR:-}" ]; then
|
||||
if [ ! -f "$LINUXDEPLOY" ]; then
|
||||
wget -q "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/${LINUXDEPLOY}"
|
||||
fi
|
||||
chmod +x "$LINUXDEPLOY"
|
||||
|
||||
test -d ${APPDIR} && rm -rf ${APPDIR}
|
||||
mkdir -p ${APPDIR}/usr/bin
|
||||
if [ -d "$APPDIR" ]; then
|
||||
rm -rf "$APPDIR"
|
||||
fi
|
||||
mkdir -p "$APPDIR/usr/bin"
|
||||
fi
|
||||
@@ -0,0 +1,46 @@
|
||||
# Contributing
|
||||
|
||||
Contributions are warmly welcome. Before you start, please read the entire document carefully.
|
||||
|
||||
## AI Policy
|
||||
|
||||
Do not use LLMs to generate substantial pieces of code. You need to fully understand every line of code you change. No exceptions.
|
||||
|
||||
Commits, issues and pull requests must be made by humans. Co-authoring by AI is not allowed.
|
||||
Looking to create an issue on the project, such as a feature request or bug report? Focus on writing what you know for sure in simple terms. We'll figure it out from there.
|
||||
|
||||
Usage of Gen-AI for visuals and audio is prohibited.
|
||||
|
||||
The only exception is LLM-translated strings generated by the scripts/translator tool.
|
||||
|
||||
## Basics
|
||||
|
||||
Before committing, make sure to format your Rust code by running:
|
||||
|
||||
```
|
||||
cargo fmt
|
||||
```
|
||||
|
||||
You should also check for any compiler warnings too:
|
||||
|
||||
```
|
||||
cargo check
|
||||
```
|
||||
|
||||
or even better:
|
||||
|
||||
```
|
||||
cargo clippy
|
||||
```
|
||||
|
||||
## Large contributions
|
||||
|
||||
If you want to submit a relatively big pull requests, it's highly advisable to create a separate issue request for it. That way we can discuss the approach and sort out the details first.
|
||||
|
||||
## Adding translations
|
||||
|
||||
Look at `scripts/translator/run.sh` for more information.
|
||||
|
||||
## Licensing
|
||||
|
||||
WayVR is developed and published under [GPL-3 License](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
Generated
+135
-144
@@ -689,6 +689,12 @@ dependencies = [
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@@ -729,6 +735,17 @@ dependencies = [
|
||||
"piper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "built"
|
||||
version = "0.8.1"
|
||||
@@ -1250,15 +1267,6 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
@@ -1410,6 +1418,7 @@ dependencies = [
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shell-words",
|
||||
"smol",
|
||||
"strum",
|
||||
"ureq",
|
||||
@@ -1735,7 +1744,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1930,6 +1939,21 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
||||
|
||||
[[package]]
|
||||
name = "freedesktop-desktop-entry"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42a69ad6111a2b572cb41e0f3542d546386e841013cee7c45d705b61a15a87dd"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gettext-rs",
|
||||
"log",
|
||||
"memchr",
|
||||
"thiserror 2.0.18",
|
||||
"unicase",
|
||||
"xdg 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
@@ -2109,6 +2133,26 @@ dependencies = [
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gettext-rs"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df5e3fa8c077b15fdfa8ce130e2bc73d663b8aaa6d51b71421b8659980b1d80"
|
||||
dependencies = [
|
||||
"gettext-sys",
|
||||
"locale_config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gettext-sys"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4caa7e4460b196107cc1bb2629488e8b6dbb7f34f6683ea6753c4ac22f590785"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"temp-dir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.14.2"
|
||||
@@ -2878,6 +2922,19 @@ version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "locale_config"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"regex",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
@@ -2939,6 +2996,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.2.0"
|
||||
@@ -3149,7 +3215,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3230,6 +3296,26 @@ dependencies = [
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-sys"
|
||||
version = "0.3.5"
|
||||
@@ -3268,7 +3354,7 @@ dependencies = [
|
||||
"objc2-core-data",
|
||||
"objc2-core-image",
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-quartz-core 0.2.2",
|
||||
"objc2-quartz-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3377,7 +3463,7 @@ dependencies = [
|
||||
"block2 0.5.1",
|
||||
"objc2 0.5.2",
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-metal 0.2.2",
|
||||
"objc2-metal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3458,17 +3544,6 @@ dependencies = [
|
||||
"objc2-foundation 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-metal"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794"
|
||||
dependencies = [
|
||||
"bitflags 2.13.0",
|
||||
"objc2 0.6.4",
|
||||
"objc2-foundation 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-open-directory"
|
||||
version = "0.3.2"
|
||||
@@ -3490,20 +3565,7 @@ dependencies = [
|
||||
"block2 0.5.1",
|
||||
"objc2 0.5.2",
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-metal 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.13.0",
|
||||
"objc2 0.6.4",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation 0.3.2",
|
||||
"objc2-metal 0.3.2",
|
||||
"objc2-metal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3531,7 +3593,7 @@ dependencies = [
|
||||
"objc2-core-location",
|
||||
"objc2-foundation 0.2.2",
|
||||
"objc2-link-presentation",
|
||||
"objc2-quartz-core 0.2.2",
|
||||
"objc2-quartz-core",
|
||||
"objc2-symbols",
|
||||
"objc2-uniform-type-identifiers",
|
||||
"objc2-user-notifications",
|
||||
@@ -3561,6 +3623,15 @@ dependencies = [
|
||||
"objc2-foundation 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
@@ -3651,7 +3722,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ovr_overlay"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/galister/ovr_overlay_oyasumi?rev=e477bd2a9e04293ea68c1e7529ef2cb131f32acc#e477bd2a9e04293ea68c1e7529ef2cb131f32acc"
|
||||
source = "git+https://github.com/galister/ovr_overlay_oyasumi?rev=3b7d24cee24aa2b1ad7dffc5d5c8568508049bdd#3b7d24cee24aa2b1ad7dffc5d5c8568508049bdd"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"derive_more",
|
||||
@@ -3666,7 +3737,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ovr_overlay_sys"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/galister/ovr_overlay_oyasumi?rev=e477bd2a9e04293ea68c1e7529ef2cb131f32acc#e477bd2a9e04293ea68c1e7529ef2cb131f32acc"
|
||||
source = "git+https://github.com/galister/ovr_overlay_oyasumi?rev=3b7d24cee24aa2b1ad7dffc5d5c8568508049bdd#3b7d24cee24aa2b1ad7dffc5d5c8568508049bdd"
|
||||
dependencies = [
|
||||
"autocxx",
|
||||
"autocxx-build",
|
||||
@@ -4054,7 +4125,7 @@ version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck 0.4.1",
|
||||
"itertools 0.14.0",
|
||||
"log",
|
||||
"multimap",
|
||||
@@ -4357,18 +4428,6 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-metal"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135"
|
||||
dependencies = [
|
||||
"objc2 0.6.4",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation 0.3.2",
|
||||
"objc2-quartz-core 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.12.0"
|
||||
@@ -4667,7 +4726,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4714,8 +4773,7 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
[[package]]
|
||||
name = "rxscreen"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afbab13f83503a8272b7150d487494992cf6c59c299dcaf5d8ffac75bad9fc96"
|
||||
source = "git+https://github.com/galister/rxscreen.git?rev=7197e1de6622b65859e6f2060b5750185e0dad2a#7197e1de6622b65859e6f2060b5750185e0dad2a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -5026,12 +5084,6 @@ version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "slabbin"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9db491c0d4152a069911a0fbdaca959691bf0b9d7110d98a7ed1c8e59b79ab30"
|
||||
|
||||
[[package]]
|
||||
name = "slice-of-array"
|
||||
version = "0.3.2"
|
||||
@@ -5394,6 +5446,12 @@ version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
||||
|
||||
[[package]]
|
||||
name = "temp-dir"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83176759e9416cf81ee66cb6508dbfe9c96f20b8b56265a39917551c23c70964"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.27.0"
|
||||
@@ -5401,10 +5459,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.4.3",
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix 1.1.4",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5739,13 +5797,17 @@ dependencies = [
|
||||
"rust-embed",
|
||||
"tracing-subscriber",
|
||||
"ureq",
|
||||
"vulkano",
|
||||
"vulkano-shaders",
|
||||
"wgui",
|
||||
"winit",
|
||||
"wlx-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.18"
|
||||
@@ -5905,70 +5967,6 @@ version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "vk-parse"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3859da4d7b98bec73e68fb65815d47a263819c415c90eed42b80440a02cbce8c"
|
||||
dependencies = [
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vulkano"
|
||||
version = "0.35.2"
|
||||
source = "git+https://github.com/galister/vulkano.git?rev=cf7f92867928a56ce16b376037c1120f2b167678#cf7f92867928a56ce16b376037c1120f2b167678"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"bytemuck",
|
||||
"crossbeam-queue",
|
||||
"foldhash 0.1.5",
|
||||
"half",
|
||||
"heck 0.4.1",
|
||||
"indexmap 2.14.0",
|
||||
"libloading 0.8.9",
|
||||
"nom 7.1.3",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"raw-window-handle",
|
||||
"raw-window-metal",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"slabbin",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"vk-parse",
|
||||
"vulkano-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vulkano-macros"
|
||||
version = "0.35.0"
|
||||
source = "git+https://github.com/galister/vulkano.git?rev=cf7f92867928a56ce16b376037c1120f2b167678#cf7f92867928a56ce16b376037c1120f2b167678"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vulkano-shaders"
|
||||
version = "0.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bf501461be7cef2893c0e62c50945add9763cc482051d29053f6157089d5ea9"
|
||||
dependencies = [
|
||||
"foldhash 0.1.5",
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"shaderc",
|
||||
"syn 2.0.118",
|
||||
"vulkano",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
@@ -6211,7 +6209,6 @@ name = "wayvr"
|
||||
version = "26.8.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ash",
|
||||
"bytes",
|
||||
"calloop 0.14.4",
|
||||
"calloop-wayland-source 0.4.1",
|
||||
@@ -6249,6 +6246,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_json5",
|
||||
"serde_yaml",
|
||||
"shaderc",
|
||||
"signal-hook",
|
||||
"slotmap",
|
||||
"smallvec",
|
||||
@@ -6261,8 +6259,6 @@ dependencies = [
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"uuid",
|
||||
"vulkano",
|
||||
"vulkano-shaders",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wayland-protocols-misc",
|
||||
@@ -6349,6 +6345,7 @@ name = "wgui"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ash",
|
||||
"bytes",
|
||||
"cosmic-text",
|
||||
"dav1d-sys",
|
||||
@@ -6360,18 +6357,18 @@ dependencies = [
|
||||
"lru",
|
||||
"ouroboros",
|
||||
"parking_lot",
|
||||
"raw-window-handle",
|
||||
"regex",
|
||||
"resvg",
|
||||
"roxmltree 0.21.1",
|
||||
"rust-embed",
|
||||
"rustc-hash",
|
||||
"serde_json",
|
||||
"shaderc",
|
||||
"slotmap",
|
||||
"smallvec",
|
||||
"strum",
|
||||
"taffy",
|
||||
"vulkano",
|
||||
"vulkano-shaders",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6425,7 +6422,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6857,6 +6854,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"freedesktop-desktop-entry",
|
||||
"glam",
|
||||
"glob",
|
||||
"identicons-svg",
|
||||
@@ -6864,7 +6862,6 @@ dependencies = [
|
||||
"idmap-derive",
|
||||
"log",
|
||||
"rodio",
|
||||
"rust-ini",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_json5",
|
||||
@@ -6982,12 +6979,6 @@ dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
|
||||
+1
-14
@@ -32,32 +32,19 @@ rust-embed = "8.9.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
serde_json5 = "0.2.1"
|
||||
shell-words = "1.1.1"
|
||||
slotmap = "1.1.1"
|
||||
smallvec = "1.15.2"
|
||||
smol = "2.0.2"
|
||||
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"] }
|
||||
vulkano = {
|
||||
version = "0.35.2",
|
||||
default-features = false,
|
||||
features = [
|
||||
"macros",
|
||||
]
|
||||
}
|
||||
vulkano-shaders = "0.35.0"
|
||||
wayland-client = { version = "0.31" }
|
||||
wayland-protocols = { version = "0.32" }
|
||||
wayland-protocols-misc = { version = "0.3.12" }
|
||||
winit = "0.30.12"
|
||||
xdg = "3.0.0"
|
||||
|
||||
[patch.crates-io]
|
||||
vulkano = {
|
||||
git = "https://github.com/galister/vulkano.git",
|
||||
rev = "cf7f92867928a56ce16b376037c1120f2b167678"
|
||||
}
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
debug = true
|
||||
|
||||
@@ -37,7 +37,7 @@ There are multiple ways to install WayVR:
|
||||
|
||||
**Note:** If you are using Monado or WiVRn, no additional setup steps are required for Flatpak Steam compatibility—most people use WayVR seamlessly with Monado/WiVRn.
|
||||
|
||||
### SteamVR via Steam Flatpak
|
||||
### SteamVR (PC) via Steam Flatpak
|
||||
|
||||
For users specifically running **SteamVR via Steam Flatpak**, follow these steps:
|
||||
|
||||
@@ -50,6 +50,20 @@ For users specifically running **SteamVR via Steam Flatpak**, follow these steps
|
||||
1. Start SteamVR.
|
||||
1. `flatpak run --command='/path/to/squashfs-root/AppRun' com.valvesoftware.Steam`
|
||||
|
||||
### Installing on Steam Frame
|
||||
|
||||
Steam Frame support is experimental. Please report issues.
|
||||
|
||||
It's possible to install and run WayVR on the Steam Frame in headless mode. You will not have access to your KDE desktop, but you will be able to run applications in 3D space around you.
|
||||
|
||||
Steps to install on Steam Frame:
|
||||
1. Grab the latest aarch64 AppImage
|
||||
- For nightly AppImages go [here](https://github.com/wayvr-org/wayvr/actions/workflows/build-appimage.yml) and select the topmost list item a ✅️
|
||||
- The downloads will be on the bottom of the page (GitHub login required).
|
||||
1. Install the AppImage using GearLever
|
||||
1. (Recommended) In Frame's SteamVR settings, set overlay quality to High.
|
||||
1. Start WayVR from the taskbar (same place where you'd start Destkop)
|
||||
|
||||
## First Start
|
||||
|
||||
**When the screen share pop-up appears, check your notifications or the terminal and select the screens in the order it requests.**
|
||||
|
||||
@@ -19,6 +19,7 @@ log.workspace = true
|
||||
rust-embed.workspace = true
|
||||
serde = { workspace = true, features = ["rc"] }
|
||||
serde_json.workspace = true
|
||||
shell-words.workspace = true
|
||||
smol = { workspace = true }
|
||||
strum.workspace = true
|
||||
uuid.workspace = true
|
||||
|
||||
@@ -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="m12 13.4l-4.9 4.9q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7l4.9-4.9l-4.9-4.9q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l4.9 4.9l4.9-4.9q.275-.275.7-.275t.7.275t.275.7t-.275.7L13.4 12l4.9 4.9q.275.275.275.7t-.275.7t-.7.275t-.7-.275z"/></svg>
|
||||
|
After Width: | Height: | Size: 468 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 22q-.825 0-1.412-.587T7 20v-3H4q-.825 0-1.412-.587T2 15v-2h6.45l1.7 2.55q.125.2.35.325t.475.125q.325 0 .6-.2t.375-.5l1.35-4.05l.85 1.3q.15.2.375.325T15 13h7v2q0 .825-.588 1.413T20 17h-3v3q0 .825-.587 1.413T15 22zm1.7-9.25l-.875-1.3q-.125-.2-.35-.325T9 11H2V9q0-.825.588-1.412T4 7h3V4q0-.825.588-1.412T9 2h6q.825 0 1.413.588T17 4v3h3q.825 0 1.413.588T22 9v2h-6.475l-1.7-2.55q-.125-.2-.35-.325T13 8q-.325 0-.587.2t-.363.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 660 B |
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs1" />
|
||||
<path fill="currentColor" d="m 10,12 c 0,-1.104569 0.895431,-2 2,-2 1.104569,0 2,0.895431 2,2 0,1.104569 -0.895431,2 -2,2 -1.104569,0 -2,-0.895431 -2,-2" id="path1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 422 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Lucide by Lucide Contributors - https://github.com/lucide-icons/lucide/blob/main/LICENSE --><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M2 17h18a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2H2m0 16V3m5 14v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1v-3"/><circle cx="16" cy="11" r="2"/><circle cx="8" cy="11" r="2"/></g></svg>
|
||||
|
After Width: | Height: | Size: 462 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="M17 10q-.825 0-1.412-.575T15 8V4q0-.85.588-1.425T17 2q.85 0 1.425.575T19 4v4q0 .85-.575 1.425T17 10M5 22q-.825 0-1.412-.587T3 20V4q0-.825.588-1.412T5 2h8v2H5v16h11v-2h2v2q0 .825-.587 1.413T16 22zm2-4v-2h7v2zm0-3v-2h5v2zm11 1h-2v-2.6q-1.925-.35-3.213-1.862T11.5 8h2q0 1.45 1.025 2.475T17 11.5q1.475 0 2.488-1.025T20.5 8h2q0 2.025-1.275 3.538T18 13.4z"/></svg>
|
||||
|
After Width: | Height: | Size: 585 B |
@@ -1,10 +1,20 @@
|
||||
<layout>
|
||||
<theme>
|
||||
<layout version="2">
|
||||
<vars>
|
||||
<var key="side_size" value="48" />
|
||||
<var key="top_size" value="40" />
|
||||
<var key="side_sprite_size" value="26" />
|
||||
<var key="side_button_size" value="48" />
|
||||
</theme>
|
||||
</vars>
|
||||
|
||||
<blueprint name="context_menu_power_options">
|
||||
<context_menu>
|
||||
<cell translation="APP_SETTINGS.RESTART_WAYVR" action="restart" sprite_src_builtin="@/dashboard/refresh.svg"/>
|
||||
<cell translation="APP_SETTINGS.CLOSE_WAYVR" action="close" sprite_src_builtin="@/dashboard/close.svg"/>
|
||||
<separator/>
|
||||
<cell translation="POWER_OPTIONS.SUSPEND" action="suspend" sprite_src_builtin="@/dashboard/sleep.svg"/>
|
||||
<cell translation="POWER_OPTIONS.SHUTDOWN" action="shutdown" sprite_src_builtin="@/dashboard/power.svg"/>
|
||||
</context_menu>
|
||||
</blueprint>
|
||||
|
||||
<template name="SideButton">
|
||||
<Button
|
||||
@@ -41,12 +51,12 @@
|
||||
align_items="center"
|
||||
gap="4"
|
||||
>
|
||||
<SideButton id="btn_side_home" src_builtin="dashboard/wayvr_dashboard_mono.svg" tooltip="HOME_SCREEN" 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_monado" src_builtin="dashboard/monado.svg" tooltip="MONADO_RUNTIME" tooltip_side="right" />
|
||||
<SideButton id="btn_side_home" src_builtin="@/dashboard/wayvr_dashboard_mono.svg" tooltip="HOME_SCREEN" 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_monado" src_builtin="@/dashboard/monado.svg" tooltip="MONADO_RUNTIME" tooltip_side="right" />
|
||||
<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>
|
||||
</div>
|
||||
<!-- REST -->
|
||||
@@ -69,7 +79,7 @@
|
||||
<!-- Close button -->
|
||||
<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>
|
||||
</div>
|
||||
|
||||
@@ -136,11 +146,14 @@
|
||||
|
||||
<!-- Left bottom side -->
|
||||
<div margin_left="8">
|
||||
<Button id="btn_power" color="background(transparent)" border_color="background(transparent)" tooltip="POWER_OPTIONS.TITLE" tooltip_side="top">
|
||||
<sprite src_builtin="@/dashboard/power.svg" width="24" height="24" margin="8" />
|
||||
</Button>
|
||||
<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 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>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<macro name="dropdown_button"
|
||||
flex_direction="row"
|
||||
border="2"
|
||||
@@ -17,7 +17,7 @@
|
||||
<div padding_top="4" padding_bottom="4">
|
||||
<rectangle width="2" height="100%" color="outline" />
|
||||
</div>
|
||||
<sprite margin_left="-4" width="30" height="30" src_builtin="dashboard/down.svg" />
|
||||
<sprite margin_left="-4" width="30" height="30" src_builtin="@/dashboard/down.svg" />
|
||||
</div>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<macro name="group_box"
|
||||
flex_direction="column"
|
||||
align_items="baseline"
|
||||
@@ -7,7 +7,14 @@
|
||||
border_color="outline"
|
||||
padding="12"
|
||||
gap="8"
|
||||
round="8" />
|
||||
round="8"/>
|
||||
|
||||
<!-- id -->
|
||||
<template name="GroupBox">
|
||||
<rectangle macro="group_box" id="rect">
|
||||
<CHILDREN/>
|
||||
</rectangle>
|
||||
</template>
|
||||
|
||||
<!-- src_builtin, text, translation -->
|
||||
<template name="GroupBoxTitle">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<template name="LoadingWithText">
|
||||
<div id="root" width="100%" height="100%" align_items="center" justify_content="center">
|
||||
<div flex_direction="row" gap="8" align_items="center" >
|
||||
<sprite id="sprite_loading" src_builtin="dashboard/loading.svg" width="32" height="32" color="on_background"/>
|
||||
<sprite id="sprite_loading" src_builtin="@/dashboard/loading.svg" width="32" height="32" color="on_background"/>
|
||||
<label translation="LOADING" weight="bold"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<template name="LoadingWithoutText">
|
||||
<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" color="on_background"/>
|
||||
<sprite id="sprite_loading" src_builtin="@/dashboard/loading.svg" width="32" height="32" color="on_background"/>
|
||||
</div>
|
||||
</template>
|
||||
</layout>
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<macro name="home_button" round="8" hover_color="primary" hover_border_color="on_primary" />
|
||||
|
||||
<template name="MenuButton">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<template name="Separator">
|
||||
<rectangle width="100%" min_height="2" color="outline" />
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<!-- tooltip, src, src_ext, name -->
|
||||
<template name="AppEntry">
|
||||
@@ -28,26 +28,26 @@
|
||||
<!--
|
||||
<div gap="4" align_items="center">
|
||||
<Button width="48" height="38">
|
||||
<sprite src_builtin="dashboard/alphabetical.svg" width="24" height="24" />
|
||||
<sprite src_builtin="@/dashboard/alphabetical.svg" width="24" height="24" />
|
||||
</Button>
|
||||
<Button width="48" height="38">
|
||||
<sprite src_builtin="dashboard/category_search.svg" width="24" height="24" />
|
||||
<sprite src_builtin="@/dashboard/category_search.svg" width="24" height="24" />
|
||||
</Button>
|
||||
<sprite src_builtin="dashboard/search.svg" width="24" height="24" />
|
||||
<sprite src_builtin="@/dashboard/search.svg" width="24" height="24" />
|
||||
<rectangle flex_grow="1" height="100%" color="#1d2e51" border_color="#294774" border="2" round="4" align_items="center" padding_left="12">
|
||||
<label text="Search" color="#FFFFFF88" weight="bold" />
|
||||
</rectangle>
|
||||
</div>
|
||||
-->
|
||||
<rectangle macro="group_box">
|
||||
<GroupBox>
|
||||
<div align_items="center" gap="8">
|
||||
<sprite src_builtin="dashboard/heart_plus.svg" color="primary" min_width="24" min_height="24"/>
|
||||
<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>
|
||||
</GroupBox>
|
||||
<div
|
||||
id="app_list_parent"
|
||||
flex_direction="row"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<layout>
|
||||
<include src="../t_separator.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_separator.xml" />
|
||||
|
||||
<template name="TierCell">
|
||||
<div gap="8" align_items="center">
|
||||
<sprite width="28" height="28" src_builtin="dashboard/medal.svg" color="${color}"/>
|
||||
<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"/>
|
||||
<sprite width="24" height="24" src_builtin="@/dashboard/person.svg"/>
|
||||
<label text="${username}" weight="bold"/>
|
||||
</rectangle>
|
||||
</template>
|
||||
@@ -32,14 +32,14 @@
|
||||
<elements>
|
||||
<div flex_direction="row" width="100%" min_height="100%" gap="16">
|
||||
<div macro="half">
|
||||
<sprite color="#FFAAAA" src_builtin="dashboard/donate.svg" min_width="48" min_height="48"/>
|
||||
<sprite color="#FFAAAA" src_builtin="@/dashboard/donate.svg" min_width="48" min_height="48"/>
|
||||
<div gap="16" align_items="center" width="100%">
|
||||
<label align="justified" wrap="1" size="15" translation="DONATE.DESCRIPTION" color="on_background"/>
|
||||
</div>
|
||||
|
||||
<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"/>
|
||||
<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>
|
||||
@@ -47,8 +47,8 @@
|
||||
<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"/>
|
||||
<Avatar icon="@/dashboard/avatars/galister.png" nickname="galister"/>
|
||||
<Avatar icon="@/dashboard/avatars/oo8dev.png" nickname="oo8dev"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- vertical separator -->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div id="running_games_list_parent" align_self="center" />
|
||||
<div id="game_list_parent" align_items="center" flex_direction="column" gap="8" />
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -1,5 +1,20 @@
|
||||
<layout>
|
||||
<include src="../t_menu_button.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_menu_button.xml" />
|
||||
|
||||
<template name="MiscButton">
|
||||
<Button
|
||||
id="${id}" macro="home_button"
|
||||
min_width="64" height="36"
|
||||
padding_left="8" padding_right="8">
|
||||
<div gap="8"
|
||||
align_items="center"
|
||||
justify_content="center"
|
||||
flex_direction="row">
|
||||
<sprite src_builtin="${icon}" width="24" height="24" />
|
||||
<label weight="bold" size="18" text="${text}" translation="${translation}" />
|
||||
</div>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<div
|
||||
@@ -9,7 +24,7 @@
|
||||
flex_grow="1"
|
||||
gap="8"
|
||||
>
|
||||
<image src_builtin="dashboard/splash.png" width="300" height="89" />
|
||||
<image src_builtin="@/dashboard/splash.png" width="300" height="89" />
|
||||
|
||||
<!-- supporters -->
|
||||
<Button
|
||||
@@ -26,24 +41,16 @@
|
||||
|
||||
<!-- main button list -->
|
||||
<div flex_direction="row" gap="8" margin_top="32">
|
||||
<MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" />
|
||||
<MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" />
|
||||
<MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" />
|
||||
<MenuButton id="btn_settings" icon="dashboard/settings.svg" translation="SETTINGS" />
|
||||
<MenuButton id="btn_apps" icon="@/dashboard/apps.svg" translation="APPLICATIONS" />
|
||||
<MenuButton id="btn_games" icon="@/dashboard/games.svg" translation="GAMES" />
|
||||
<MenuButton id="btn_monado" icon="@/dashboard/monado.svg" text="Monado" />
|
||||
<MenuButton id="btn_settings" icon="@/dashboard/settings.svg" translation="SETTINGS" />
|
||||
</div>
|
||||
|
||||
<div gap="8">
|
||||
<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" />
|
||||
</Button>
|
||||
|
||||
<Button id="btn_website" macro="home_button" tooltip_str="wayvr.org">
|
||||
<sprite src_builtin="dashboard/globe.svg" width="32" height="32" margin="16" />
|
||||
</Button>
|
||||
|
||||
<Button id="btn_donate" macro="home_button" tooltip="DONATE.SUPPORT_US">
|
||||
<sprite src_builtin="dashboard/opencollective.svg" width="32" height="32" margin="16" />
|
||||
</Button>
|
||||
<MiscButton id="btn_welcome_screen" icon="@/dashboard/welcome.svg" translation="APP_SETTINGS.TUTORIAL"/>
|
||||
<MiscButton id="btn_website" icon="@/dashboard/globe.svg" text="wayvr.org"/>
|
||||
<MiscButton id="btn_donate" icon="@/dashboard/opencollective.svg" translation="DONATE.SUPPORT_US"/>
|
||||
</div>
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div gap="4">
|
||||
<Tabs id="tabs">
|
||||
<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="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" />
|
||||
</Tabs>
|
||||
<div gap="4" id="content" width="100%">
|
||||
<!-- filled-in at runtime -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<!-- name, limit_min, limit_max -->
|
||||
<template name="DebugGraph">
|
||||
@@ -15,13 +15,13 @@
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<rectangle macro="group_box">
|
||||
<GroupBoxTitle src_builtin="dashboard/apps.svg" text="Sessions" />
|
||||
<GroupBox>
|
||||
<GroupBoxTitle src_builtin="@/dashboard/apps.svg" text="Sessions" />
|
||||
<div id="session_list_parent" flex_wrap="wrap" flex_direction="row" gap="8" />
|
||||
<GroupBoxTitle src_builtin="dashboard/not_a_bug.svg" text="Debug timings" />
|
||||
<GroupBoxTitle src_builtin="@/dashboard/not_a_bug.svg" text="Debug timings" />
|
||||
<div id="timings_parent" flex_wrap="wrap" flex_direction="row" gap="8">
|
||||
<label text="Please select which session you want to monitor" />
|
||||
</div>
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -1,56 +1,57 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<macro name="slider" width="100%" height="24"/>
|
||||
<template name="CKRow">
|
||||
<div gap="8" width="~s_width">
|
||||
<CHILDREN/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<theme>
|
||||
<!-- title, id -->
|
||||
<template name="CKSlider">
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="${title}"/>
|
||||
<Slider id="${id}" min_value="0" max_value="100" width="100%" height="24"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- title, id -->
|
||||
<template name="CKColSel">
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="${title}"/>
|
||||
<ColorSelector id="cs_keying" height="24" width="100%"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<vars>
|
||||
<var key="s_width" value="500"/>
|
||||
</theme>
|
||||
</vars>
|
||||
|
||||
<elements>
|
||||
<div flex_direction="column" gap="8">
|
||||
<rectangle macro="group_box">
|
||||
<GroupBoxTitle src_builtin="dashboard/settings.svg" translation="GENERAL_SETTINGS" />
|
||||
<!-- headset brightness -->
|
||||
<GroupBox>
|
||||
<GroupBoxTitle src_builtin="@/dashboard/settings.svg" translation="GENERAL_SETTINGS" />
|
||||
|
||||
<label translation="DISPLAY_BRIGHTNESS" />
|
||||
<Slider id="slider_brightness" width="300" height="24" min_value="0" max_value="140" />
|
||||
</rectangle>
|
||||
<rectangle macro="group_box">
|
||||
<GroupBoxTitle src_builtin="dashboard/settings.svg" translation="APP_SETTINGS.COLOR_KEYING" />
|
||||
<div gap="8" width="~s_width">
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="Color"/>
|
||||
<ColorSelector id="cs_keying" height="24" width="100%"/>
|
||||
</div>
|
||||
</GroupBox>
|
||||
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="Despill"/>
|
||||
<Slider id="slider_keying_despill" min_value="0" max_value="100" macro="slider"/>
|
||||
</div>
|
||||
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="Curve (0 = disabled)"/>
|
||||
<Slider id="slider_keying_curve" min_value="0" max_value="100" macro="slider"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- color keying -->
|
||||
<GroupBox>
|
||||
<GroupBoxTitle src_builtin="@/dashboard/settings.svg" translation="APP_SETTINGS.COLOR_KEYING" />
|
||||
<CKRow>
|
||||
<CKColSel title="Color" id="cs_keying"/>
|
||||
<CKSlider title="Despill" id="slider_keying_despill"/>
|
||||
<CKSlider title="Curve (0 = disabled)" id="slider_keying_curve"/>
|
||||
</CKRow>
|
||||
|
||||
<div gap="8" width="~s_width">
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="Hue range"/>
|
||||
<Slider id="slider_keying_hue_range" min_value="0" max_value="100" macro="slider"/>
|
||||
</div>
|
||||
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="Saturation range"/>
|
||||
<Slider id="slider_keying_saturation_range" min_value="0" max_value="100" macro="slider"/>
|
||||
</div>
|
||||
|
||||
<div gap="8" flex_direction="column" width="100%">
|
||||
<label text="Value range"/>
|
||||
<Slider id="slider_keying_value_range" min_value="0" max_value="100" macro="slider"/>
|
||||
</div>
|
||||
</div>
|
||||
</rectangle>
|
||||
<CKRow>
|
||||
<CKSlider title="Hue range" id="slider_keying_hue_range"/>
|
||||
<CKSlider title="Saturation range" id="slider_keying_saturation_range"/>
|
||||
<CKSlider title="Value range" id="slider_keying_value_range"/>
|
||||
</CKRow>
|
||||
</GroupBox>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,5 +1,5 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<!-- key: str, value: str -->
|
||||
<template name="BoolFlag">
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<!-- name, checked, flag_* -->
|
||||
<template name="Cell">
|
||||
<rectangle macro="group_box">
|
||||
<GroupBox>
|
||||
<CheckBox id="checkbox" text="${name}" checked="${checked}" />
|
||||
<div flex_direction="row" gap="8" flex_wrap="wrap">
|
||||
<BoolFlag key="Active:" value="${flag_active}" />
|
||||
@@ -21,15 +21,15 @@
|
||||
<BoolFlag key="Primary:" value="${flag_primary}" />
|
||||
<BoolFlag key="Visible:" value="${flag_visible}" />
|
||||
</div>
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<rectangle macro="group_box">
|
||||
<GroupBoxTitle src_builtin="dashboard/cpu.svg" translation="PROCESS_LIST" />
|
||||
<GroupBox>
|
||||
<GroupBoxTitle src_builtin="@/dashboard/cpu.svg" translation="PROCESS_LIST" />
|
||||
<div id="list_parent" flex_direction="column" gap="8">
|
||||
<!-- filled at runtime -->
|
||||
</div>
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -1,6 +1,6 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<include src="../t_dropdown_button.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
<include src="@/gui/t_dropdown_button.xml" />
|
||||
|
||||
<template name="SettingsGroupBox">
|
||||
<rectangle macro="group_box" id="${id}" flex_grow="1">
|
||||
@@ -31,6 +31,27 @@
|
||||
<RadioBox text="${text}" translation="${translation}" value="${value}" tooltip="${tooltip}" />
|
||||
</template>
|
||||
|
||||
<!-- title, sprite, color, tooltip_str -->
|
||||
<template name="DiagnosticsRow">
|
||||
<div align_items="center">
|
||||
<label text="${title}" weight="bold" min_width="140"/>
|
||||
<Button tooltip_str="${tooltip_str}" color="background(transparent)">
|
||||
<sprite width="24" height="24" color="${color}" src_builtin="${sprite}" parent_color="ignore"/>
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- name, info -->
|
||||
<template name="DiagnosticsDrmCard">
|
||||
<GroupBox>
|
||||
<div gap="8">
|
||||
<sprite width="24" height="24" src_builtin="@/dashboard/gpu.svg"/>
|
||||
<label text="${name}"/>
|
||||
</div>
|
||||
<label text="${info}"/>
|
||||
</GroupBox>
|
||||
</template>
|
||||
|
||||
<template name="StatRow">
|
||||
<div flex_direction="row" justify_content="space_between" align_items="center" gap="12" width="100%">
|
||||
<label weight="bold" translation="${translation}" />
|
||||
@@ -56,7 +77,7 @@
|
||||
<div id="${id}_root" flex_direction="row">
|
||||
<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>
|
||||
<div padding_left="8">
|
||||
<label align="left" text="${text}" weight="bold" overflow="hidden" />
|
||||
@@ -69,15 +90,16 @@
|
||||
<elements>
|
||||
<div gap="4">
|
||||
<Tabs id="tabs">
|
||||
<Tab macro="tab_style" name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
||||
<Tab macro="tab_style" name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="dashboard/globe.svg" />
|
||||
<Tab macro="tab_style" name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
||||
<Tab macro="tab_style" name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
||||
<Tab macro="tab_style" name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="dashboard/drag.svg" />
|
||||
<Tab macro="tab_style" name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
||||
<Tab macro="tab_style" name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
||||
<Tab macro="tab_style" name="statistics" translation="APP_SETTINGS.STATISTICS" sprite_src_builtin="dashboard/barchart.svg" />
|
||||
<Tab macro="tab_style" name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
||||
<Tab macro="tab_style" name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="@/dashboard/palette.svg" />
|
||||
<Tab macro="tab_style" name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="@/dashboard/globe.svg" />
|
||||
<Tab macro="tab_style" name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="@/dashboard/options.svg" />
|
||||
<Tab macro="tab_style" name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="@/dashboard/controller.svg" />
|
||||
<Tab macro="tab_style" name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="@/dashboard/drag.svg" />
|
||||
<Tab macro="tab_style" name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="@/dashboard/blocks.svg" />
|
||||
<Tab macro="tab_style" name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="@/dashboard/apps.svg" />
|
||||
<Tab macro="tab_style" name="statistics" translation="APP_SETTINGS.STATISTICS" sprite_src_builtin="@/dashboard/barchart.svg" />
|
||||
<Tab macro="tab_style" name="diagnostics" translation="APP_SETTINGS.DIAGNOSTICS.TITLE" sprite_src_builtin="@/dashboard/diagnostics.svg" />
|
||||
<Tab macro="tab_style" name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="@/dashboard/cpu.svg" />
|
||||
</Tabs>
|
||||
<div flex_wrap="wrap" justify_content="stretch" gap="4" id="settings_root" width="100%">
|
||||
<!-- filled-in at runtime -->
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<div id="common_options_parent" flex_direction="column" gap="8"/>
|
||||
<rectangle macro="group_box">
|
||||
<GroupBoxTitle src_builtin="dashboard/gravity.svg" translation="APP_SETTINGS.SPACE_GRAVITY_GRAVITY" />
|
||||
<GroupBox>
|
||||
<GroupBoxTitle src_builtin="@/dashboard/gravity.svg" translation="APP_SETTINGS.SPACE_GRAVITY_GRAVITY" />
|
||||
<div id="gravity_enabled_parent"/>
|
||||
<div id="space_gravity_parent" flex_direction="column" gap="8">
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<template name="Pip">
|
||||
<rectangle id="pip" width="8" height="8" round="100%" color="${COLOR}"/>
|
||||
</template>
|
||||
@@ -12,11 +12,11 @@
|
||||
<!-- Page buttons -->
|
||||
<div position="absolute" align_self="end" justify_self="end" width="100%" flex_direction="column" align_items="center" margin_bottom="8">
|
||||
<div flex_direction="row" gap="8" align_items="center">
|
||||
<Button id="btn_prev" width="32" height="32" round="100%" sprite_src_builtin="dashboard/arrow_left.svg" />
|
||||
<Button id="btn_prev" width="32" height="32" round="100%" sprite_src_builtin="@/dashboard/arrow_left.svg" />
|
||||
<div id="pips" gap="4" align_items="center">
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
<Button id="btn_next" width="32" height="32" round="100%" sprite_src_builtin="dashboard/arrow_right.svg" />
|
||||
<Button id="btn_next" width="32" height="32" round="100%" sprite_src_builtin="@/dashboard/arrow_right.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<!-- icon, title -->
|
||||
<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">
|
||||
@@ -19,4 +19,13 @@
|
||||
<macro name="video_overlay_component" looping="1" width="100%" height="auto" max_height="100%" aspect_ratio="1.777777" position="relative"/>
|
||||
|
||||
<macro name="video_overlay_content" new_pass="1" position="absolute" width="100%" height="100%" padding_bottom="32"/>
|
||||
|
||||
<!-- src_builtin, aspect_ratio -->
|
||||
<template name="WelcomeVideo">
|
||||
<Video macro="video_overlay_component" src_builtin="${src_builtin}" aspect_ratio="${aspect_ratio}">
|
||||
<div macro="video_overlay_content">
|
||||
<CHILDREN/>
|
||||
</div>
|
||||
</Video>
|
||||
</template>
|
||||
</layout>
|
||||
@@ -1,6 +1,6 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<image src_builtin="dashboard/splash.png" min_width="336" min_height="100" />
|
||||
<image src_builtin="@/dashboard/splash.png" min_width="336" min_height="100" />
|
||||
|
||||
<rectangle color="#FFFFFF11" width="100%" height="2"/>
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
<label size="20" translation="WELCOME.GUIDE_INTRO"/>
|
||||
|
||||
<div gap="4" align_items="center" margin_top="8">
|
||||
<sprite min_width="16" min_height="16" src_builtin="dashboard/info.svg" color="on_background"/>
|
||||
<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"/>
|
||||
</div>
|
||||
|
||||
<div gap="4" align_items="center">
|
||||
<sprite min_width="16" min_height="16" src_builtin="dashboard/info.svg" color="on_background"/>
|
||||
<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"/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<include src_builtin="welcome_common.xml"/>
|
||||
|
||||
<elements>
|
||||
<rectangle color="#103142" width="100%" height="100%" position="absolute"/>
|
||||
<Video macro="video_overlay_component" src_builtin="video/onboarding_watch.ivf" aspect_ratio="1.0">
|
||||
<div macro="video_overlay_content">
|
||||
<PageTitle icon="dashboard/watch.svg" translation="WELCOME.WATCH"/>
|
||||
<div position="relative" align_self="end" padding="16">
|
||||
<TextDesc translation="WELCOME.LOOK_AT_LEFT_WRIST"/>
|
||||
</div>
|
||||
|
||||
<WelcomeVideo src_builtin="@/video/onboarding_watch.ivf" aspect_ratio="1.0">
|
||||
<PageTitle icon="@/dashboard/watch.svg" translation="WELCOME.WATCH"/>
|
||||
<div position="relative" align_self="end" padding="16">
|
||||
<TextDesc translation="WELCOME.LOOK_AT_LEFT_WRIST"/>
|
||||
</div>
|
||||
</Video>
|
||||
</WelcomeVideo>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,14 +1,12 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<include src_builtin="welcome_common.xml"/>
|
||||
|
||||
<elements>
|
||||
<Video macro="video_overlay_component" src_builtin="video/onboarding_double_press.ivf">
|
||||
<div macro="video_overlay_content">
|
||||
<PageTitle icon="dashboard/panorama.svg" translation="WELCOME.WORKING_SET"/>
|
||||
<div position="relative" align_self="end" padding="16">
|
||||
<TextDesc translation="WELCOME.DOUBLE_PRESS_TO_TOGGLE"/>
|
||||
</div>
|
||||
<WelcomeVideo src_builtin="@/video/onboarding_double_press.ivf">
|
||||
<PageTitle icon="@/dashboard/panorama.svg" translation="WELCOME.WORKING_SET"/>
|
||||
<div position="relative" align_self="end" padding="16">
|
||||
<TextDesc translation="WELCOME.DOUBLE_PRESS_TO_TOGGLE"/>
|
||||
</div>
|
||||
</Video>
|
||||
</WelcomeVideo>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,19 +1,17 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<include src_builtin="welcome_common.xml"/>
|
||||
|
||||
<elements>
|
||||
<Video macro="video_overlay_component" src_builtin="video/onboarding_laser_colors.ivf">
|
||||
<div macro="video_overlay_content">
|
||||
<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">
|
||||
<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="#FFAA00" translation="WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER"/>
|
||||
<label size="12" weight="bold" color="#FF88FF" translation="WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER"/>
|
||||
</rectangle>
|
||||
<label wrap="1" size="18" width="450" weight="bold" color="#ffffff" shadow="#000000" translation="WELCOME.LASER_FUNCTIONALITY"/>
|
||||
</div>
|
||||
<WelcomeVideo src_builtin="@/video/onboarding_laser_colors.ivf">
|
||||
<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">
|
||||
<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="#FFAA00" translation="WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER"/>
|
||||
<label size="12" weight="bold" color="#FF88FF" translation="WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER"/>
|
||||
</rectangle>
|
||||
<label wrap="1" size="18" width="450" weight="bold" color="#ffffff" shadow="#000000" translation="WELCOME.LASER_FUNCTIONALITY"/>
|
||||
</div>
|
||||
</Video>
|
||||
</WelcomeVideo>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,20 +1,18 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<include src_builtin="welcome_common.xml"/>
|
||||
|
||||
<elements>
|
||||
<rectangle color="#0A2939" width="100%" height="100%" position="absolute"/>
|
||||
<Video macro="video_overlay_component" src_builtin="video/onboarding_center_marker.ivf" aspect_ratio="1.33333">
|
||||
<div macro="video_overlay_content">
|
||||
<PageTitle icon="dashboard/panorama.svg" translation="WELCOME.MOVING_YOUR_SET"/>
|
||||
<div position="relative" align_self="end" padding="16" flex_direction="column" gap="4">
|
||||
<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"/>
|
||||
<div align_items="center" gap="8">
|
||||
<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"/>
|
||||
</div>
|
||||
<WelcomeVideo src_builtin="@/video/onboarding_center_marker.ivf" aspect_ratio="1.33333">
|
||||
<PageTitle icon="@/dashboard/panorama.svg" translation="WELCOME.MOVING_YOUR_SET"/>
|
||||
<div position="relative" align_self="end" padding="16" flex_direction="column" gap="4">
|
||||
<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"/>
|
||||
<div align_items="center" gap="8">
|
||||
<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"/>
|
||||
</div>
|
||||
</div>
|
||||
</Video>
|
||||
</WelcomeVideo>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,9 +1,9 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<include src_builtin="welcome_common.xml"/>
|
||||
|
||||
<elements>
|
||||
<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">
|
||||
<TextDescBig translation="WELCOME.ALL_SET" color="tertiary"/>
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
<label size="16" wrap="1" translation="WELCOME.BASICS"/>
|
||||
<label size="16" wrap="1" translation="WELCOME.FEATURES_DOCUMENTATION"/>
|
||||
<Button id="btn_wayvr_org" align_self="baseline" min_height="32">
|
||||
<sprite src_builtin="dashboard/globe.svg" width="24" height="24" 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" />
|
||||
</Button>
|
||||
|
||||
<rectangle color="#FFFFFF33" width="100%" min_height="2"/>
|
||||
|
||||
<Button id="btn_home_screen" min_height="48" >
|
||||
<sprite src_builtin="dashboard/check.svg" width="32" height="32" margin="8"/>
|
||||
<sprite src_builtin="@/dashboard/check.svg" width="32" height="32" margin="8"/>
|
||||
<label color="on_background" size="20" weight="bold" translation="WELCOME.FINISH_TUTORIAL" margin_right="8" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<template name="Subtext">
|
||||
<div flex_direction="row" gap="8" max_width="100%">
|
||||
<label weight="bold" text="${title}" wrap="1" />
|
||||
@@ -10,8 +10,8 @@
|
||||
<sprite src_ext="${path}" width="96" height="96" />
|
||||
</template>
|
||||
|
||||
<include src="../t_separator.xml" />
|
||||
<include src="../t_group_box.xml" />
|
||||
<include src="@/gui/t_separator.xml" />
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<div flex_direction="row" gap="16" flex_grow="1">
|
||||
@@ -45,15 +45,15 @@
|
||||
<CheckBox id="cb_autostart" translation="APP_LAUNCHER.AUTOSTART" align_self="baseline"/>
|
||||
<div flex_direction="row" align_items="end" justify_content="center" gap="8" margin_top="8">
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<layout>
|
||||
<include src_builtin="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src_builtin="@/gui/t_group_box.xml" />
|
||||
|
||||
<!-- device_name, device_icon -->
|
||||
<template name="DeviceSlider">
|
||||
<rectangle macro="group_box">
|
||||
<GroupBox id="rect">
|
||||
<div width="100%" align_items="center" justify_content="center" gap="8">
|
||||
<sprite src_builtin="${device_icon}" width="16" height="16" color="on_background" />
|
||||
<sprite src_builtin="${device_icon}" width="24" height="24" color="on_background" />
|
||||
<label text="${device_name}" margin_right="8" size="12" weight="bold" color="on_background" />
|
||||
</div>
|
||||
<div width="100%" align_items="center">
|
||||
<CheckBox id="checkbox" />
|
||||
<Button sprite_src_builtin="${volume_icon}" id="btn_mute" width="32" />
|
||||
<Slider id="slider" flex_grow="1" height="16" min_value="0" max_value="150" margin_left="8" />
|
||||
<CheckBox id="checkbox" tooltip="AUDIO.SWITCH_TO_THIS_DEVICE" />
|
||||
<Slider id="slider" flex_grow="1" height="16" min_value="0" max_value="150" margin_left="8" margin_right="8" />
|
||||
<Button sprite_src_builtin="${volume_icon}" id="btn_mute" width="32" height="32" />
|
||||
</div>
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</template>
|
||||
|
||||
<!-- card_name, profile_name -->
|
||||
<template name="Card">
|
||||
<rectangle macro="group_box">
|
||||
<GroupBox>
|
||||
<div width="100%" align_items="center" justify_content="center">
|
||||
<label text="${card_name}" size="12" weight="bold" color="on_background" />
|
||||
</div>
|
||||
<Button id="btn_card" text="${profile_name}" width="100%" height="32" />
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</template>
|
||||
|
||||
<template name="SelectAudioProfileText">
|
||||
<div align_items="center" gap="8">
|
||||
<Button width="48" height="32" id="btn_back">
|
||||
<sprite src_builtin="dashboard/back.svg" width="24" height="24" color="on_background" />
|
||||
<sprite src_builtin="@/dashboard/back.svg" width="24" height="24" color="on_background" />
|
||||
</Button>
|
||||
<label translation="AUDIO.SELECT_AUDIO_CARD_PROFILE" size="14" weight="bold" />
|
||||
</div>
|
||||
@@ -47,24 +47,33 @@
|
||||
|
||||
<elements>
|
||||
<div flex_direction="column" gap="4">
|
||||
<div id="devices" flex_direction="column" gap="4" max_height="400" overflow_y="scroll">
|
||||
<!--
|
||||
this div shouldn't be technically needed, but there's a bug in
|
||||
the newest taffy version (or we're doing something wrong),
|
||||
causing the scrollbar to show up, even if it's not overflowing.
|
||||
OVERFLOW_START_THRESHOLD_UNITS is already set to 3, but it's not
|
||||
sufficient enough in this case?? (margin_bottom="4" fixes that).
|
||||
-->
|
||||
<div width="100%" flex_direction="column" max_height="400" overflow_y="scroll">
|
||||
<div id="devices" width="100%" flex_direction="column" gap="4" margin_bottom="4">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- bottom buttons -->
|
||||
<div flex_direction="row" gap="4">
|
||||
<Button
|
||||
id="btn_auto"
|
||||
sprite_src_builtin="dashboard/magic_wand.svg"
|
||||
sprite_src_builtin="@/dashboard/magic_wand.svg"
|
||||
min_width="32"
|
||||
tooltip="AUDIO.AUTO_SWITCH_TO_VR_AUDIO"
|
||||
color="primary"
|
||||
sprite_color="on_primary"
|
||||
tooltip_side="right" />
|
||||
|
||||
<BottomButton id="btn_sinks" src_builtin="dashboard/volume.svg" translation="AUDIO.SPEAKERS" />
|
||||
<BottomButton id="btn_sources" src_builtin="dashboard/microphone.svg" translation="AUDIO.MICROPHONES" />
|
||||
<BottomButton id="btn_cards" src_builtin="dashboard/cpu.svg" translation="AUDIO.CARDS" />
|
||||
<BottomButton id="btn_sinks" src_builtin="@/dashboard/volume.svg" translation="AUDIO.SPEAKERS" />
|
||||
<BottomButton id="btn_sources" src_builtin="@/dashboard/microphone.svg" translation="AUDIO.MICROPHONES" />
|
||||
<BottomButton id="btn_cards" src_builtin="@/dashboard/cpu.svg" translation="AUDIO.CARDS" />
|
||||
</div>
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<!-- used at runtime [!!!] -->
|
||||
<include src="../t_dropdown_button.xml" />
|
||||
<include src="@/gui/t_dropdown_button.xml" />
|
||||
|
||||
<!-- id, min, max, step, value, value2, tooltip -->
|
||||
<template name="ThresholdSlider">
|
||||
@@ -14,7 +14,7 @@
|
||||
<rectangle macro="group_box" id="${id}">
|
||||
<!-- top row -->
|
||||
<div flex_direction="row" gap="8" align_items="center">
|
||||
<sprite src_builtin="dashboard/controller.svg" width="24" height="24" color="on_background"/>
|
||||
<sprite src_builtin="@/dashboard/controller.svg" width="24" height="24" color="on_background"/>
|
||||
<label translation="${translation}" color="primary" weight="bold" size="14" />
|
||||
</div>
|
||||
<!-- filled-in at runtime -->
|
||||
@@ -27,8 +27,8 @@
|
||||
<div id="list_parent" flex_direction="column" gap="6" width="100%"></div>
|
||||
</div>
|
||||
<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_save" sprite_src_builtin="dashboard/check.svg" min_width="100" height="32" translation="APP_SETTINGS.SAVE" />
|
||||
<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" />
|
||||
</rectangle>
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<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" >
|
||||
@@ -20,7 +20,7 @@
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="center" overflow_y="scroll">
|
||||
<div id="list_parent" flex_grow="1" flex_wrap="wrap" flex_direction="row" gap="4" width="100%" justify_content="center"></div>
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<template name="DialogBoxButton">
|
||||
<Button id="btn" translation="CLOSE_WINDOW" align_self="start" sprite_src_builtin="${icon}"/>
|
||||
<Button id="btn" translation="CLOSE_WINDOW" align_self="start" sprite_src_builtin="${icon}"
|
||||
text_size="16"
|
||||
padding_left="16" padding_right="16"
|
||||
padding_top="8" padding_bottom="8"/>
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<layout>
|
||||
<include src="../t_separator.xml"/>
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_separator.xml"/>
|
||||
|
||||
<template name="btn_close">
|
||||
<Button id="btn" translation="CLOSE_WINDOW" align_self="start" sprite_src_builtin="dashboard/check.svg"/>
|
||||
<Button id="btn" translation="CLOSE_WINDOW" align_self="start" sprite_src_builtin="@/dashboard/check.svg"/>
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div flex_direction="row" gap="16" align_items="center">
|
||||
<div id="cover_art_parent" />
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<label id="label_description" wrap="1" text="No description available" />
|
||||
<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" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div flex_direction="column" padding_top="8" padding_bottom="8">
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" justify_content="center" />
|
||||
</div>
|
||||
<div align_items="center" justify_content="center" gap="16">
|
||||
<Button id="btn_prev" sprite_src_builtin="dashboard/arrow_left.svg" width="32" height="32" />
|
||||
<Button id="btn_prev" sprite_src_builtin="@/dashboard/arrow_left.svg" width="32" height="32" />
|
||||
<label id="label_page" text="Page X" weight="bold" />
|
||||
<Button id="btn_next" sprite_src_builtin="dashboard/arrow_right.svg" width="32" height="32" />
|
||||
<Button id="btn_next" sprite_src_builtin="@/dashboard/arrow_right.svg" width="32" height="32" />
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -1,8 +1,8 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<!-- id, text -->
|
||||
<template name="InputProfileButton">
|
||||
<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"/>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div
|
||||
consume_mouse_events="1"
|
||||
@@ -20,10 +20,10 @@
|
||||
<rectangle position="absolute" width="100%" height="3" round="4" color="highlight(opacity-0.1)" />
|
||||
|
||||
<!-- Top bar contents -->
|
||||
<div gap="16" align_items="center">
|
||||
<div gap="16" align_items="center" id="top_bar_contents">
|
||||
<!-- Back button -->
|
||||
<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" color="on_background_contrast" />
|
||||
<sprite src_builtin="@/dashboard/back.svg" width="24" height="24" color="on_background_contrast" />
|
||||
</Button>
|
||||
|
||||
<!-- Title -->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
|
||||
<!--
|
||||
parameters:
|
||||
@@ -12,7 +12,7 @@
|
||||
<Button id="button" sprite_src_builtin="${sprite}" text="${text}"/>
|
||||
</template>
|
||||
|
||||
<include src="../t_separator.xml"/>
|
||||
<include src="@/gui/t_separator.xml"/>
|
||||
|
||||
<elements>
|
||||
<div gap="8" flex_direction="column" min_width="100%" overflow_y="scroll">
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div id="list" gap="8" flex_wrap="wrap" align_self="baseline">
|
||||
<!-- filled-in at runtime -->
|
||||
<div flex_direction="column" overflow_y="scroll">
|
||||
<div id="list" gap="8" flex_direction="row" flex_wrap="wrap">
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,20 +1,20 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
<layout version="2">
|
||||
<include src="@/gui/t_group_box.xml" />
|
||||
|
||||
<template name="RunningGameCell">
|
||||
<rectangle macro="group_box" flex_direction="row">
|
||||
<Button id="btn_stop" sprite_src_builtin="dashboard/remove_circle.svg" tooltip="PROCESS.STOP" />
|
||||
<Button id="btn_kill" sprite_src_builtin="dashboard/knife.svg" tooltip="PROCESS.FORCE_KILL" />
|
||||
<GroupBox>
|
||||
<Button id="btn_stop" sprite_src_builtin="@/dashboard/remove_circle.svg" tooltip="PROCESS.STOP" />
|
||||
<Button id="btn_kill" sprite_src_builtin="@/dashboard/knife.svg" tooltip="PROCESS.FORCE_KILL" />
|
||||
<label id="label_name" weight="bold" />
|
||||
</rectangle>
|
||||
</GroupBox>
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<div align_items="center" gap="8">
|
||||
<Button id="btn_refresh" tooltip="REFRESH" width="32" height="32" sprite_src_builtin="dashboard/refresh.svg" />
|
||||
<sprite src_builtin="dashboard/cpu.svg" width="24" height="24" />
|
||||
<Button id="btn_refresh" tooltip="REFRESH" width="32" height="32" sprite_src_builtin="@/dashboard/refresh.svg" />
|
||||
<sprite src_builtin="@/dashboard/cpu.svg" width="24" height="24" />
|
||||
<label translation="GAME_LIST.RUNNING_GAMES_LIST" />
|
||||
</div>
|
||||
<div id="list_parent" gap="8" />
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -1,11 +1,11 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
<elements>
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
||||
<div flex_direction="column" gap="8" width="100%" >
|
||||
<div flex_direction="row" gap="4" align_self="end">
|
||||
<Button id="btn_refresh" tooltip="RELOAD_FROM_DISK" width="32" height="32" sprite_src_builtin="dashboard/refresh.svg" />
|
||||
<Button id="btn_download_skymaps" height="32" translation="APP_SETTINGS.BROWSE_ONLINE_CATALOG" sprite_src_builtin="dashboard/download.svg"/>
|
||||
<Button id="btn_refresh" tooltip="RELOAD_FROM_DISK" width="32" height="32" sprite_src_builtin="@/dashboard/refresh.svg" />
|
||||
<Button id="btn_download_skymaps" height="32" translation="APP_SETTINGS.BROWSE_ONLINE_CATALOG" sprite_src_builtin="@/dashboard/download.svg"/>
|
||||
</div>
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" />
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" overflow_y="scroll" justify_content="center"/>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,4 +1,4 @@
|
||||
<layout>
|
||||
<layout version="2">
|
||||
|
||||
<!--
|
||||
ids:
|
||||
@@ -15,9 +15,12 @@
|
||||
flex_direction="column"
|
||||
gap="4"
|
||||
width="256"
|
||||
max_width="450"
|
||||
height="200"
|
||||
align_items="center"
|
||||
flex_grow="1"
|
||||
align_self="start">
|
||||
<image id="image_preview" width="100%" height="128" round="6">
|
||||
<image id="image_preview" width="100%" aspect_ratio="2.0" round="6">
|
||||
<!-- new_pass is required, because we need to render rectangles at the top of the image. Sorry. -->
|
||||
<div new_pass="1" id="resolution_pips" gap="4" margin="6"/>
|
||||
</image>
|
||||
@@ -34,7 +37,7 @@
|
||||
-->
|
||||
<template name="ResolutionPip">
|
||||
<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" color="#FFFFFF" 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" parent_color="ignore"/>
|
||||
</rectangle>
|
||||
</template>
|
||||
</layout>
|
||||
@@ -1,9 +0,0 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<rectangle macro="group_box" flex_direction="row" align_items="center">
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" flex_grow="1" />
|
||||
</rectangle>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,16 +0,0 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<div gap="16" flex_direction="column" width="100%" justify_self="center" align_items="center" justify_content="center">
|
||||
<rectangle macro="group_box" align_items="center">
|
||||
<div id="window_parent" />
|
||||
<div gap="8">
|
||||
<Button id="btn_show_hide" text="showhide" sprite_src_builtin="dashboard/eye.svg" />
|
||||
<Button id="btn_close" translation="CLOSE_WINDOW" sprite_src_builtin="dashboard/remove_circle.svg" />
|
||||
<Button id="btn_kill" translation="TERMINATE_PROCESS" sprite_src_builtin="dashboard/remove_circle.svg" />
|
||||
</div>
|
||||
</rectangle>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -97,7 +97,10 @@
|
||||
"RIGHT": "Rechts",
|
||||
"COMPONENT": "Aktivierungsart",
|
||||
"SUBPATH": "Bedienelement",
|
||||
"THRESHOLD": "Aktivieren bei Überschreiten des oberen Wertes\nDeaktivieren bei Unterschreiten des unteren Wertes"
|
||||
"THRESHOLD": "Aktivieren bei Überschreiten des oberen Wertes\nDeaktivieren bei Unterschreiten des unteren Wertes",
|
||||
"CHORD": "Chord",
|
||||
"CHORD_ADD_INPUT": "Chord-Input hinzufügen",
|
||||
"CHORD_INPUT_HAND": "Eingabehand"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "Online-Katalog durchsuchen...",
|
||||
"BROWSE_SKYMAPS": "Skymaps durchsuchen",
|
||||
@@ -194,8 +197,6 @@
|
||||
"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",
|
||||
@@ -205,7 +206,6 @@
|
||||
"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",
|
||||
@@ -247,7 +247,25 @@
|
||||
"STATISTICS": "Statistiken",
|
||||
"ROTATIONS": "HMD-Rotationen",
|
||||
"SESSION_TIME": "Sitzungszeit",
|
||||
"LENS_SEPARATION_MM": "Linsenabstand (mm)"
|
||||
"LENS_SEPARATION_MM": "Linsenabstand (mm)",
|
||||
"MIDDLE_GRABS_SINGLE": "Mittelklick-Modifier greift einzeln",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "Greifen mit dem Mittelklick-Modifier (lila Laser) \ngreift einzelne Overlays statt des gesamten Sets",
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "Erforderlich für Lautsprecher-/Mikrofonsteuerung und das Wechseln der Soundkarte",
|
||||
"CAGE": "Empfohlen bei Inkompatibilitäten mit einigen X11-Anwendungen (Kompatibilitätsmodus)",
|
||||
"XWAYLAND_SATELLITE": "Empfohlen, wenn X11 (Xwayland) Anwendungen im nativen Modus ausgeführt werden sollen",
|
||||
"XDG_OPEN": "Erforderlich zum Öffnen von URLs oder Steam-Spielen"
|
||||
},
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "CPU-zugänglicher VRAM: {NUM} MiB",
|
||||
"TITLE": "Diagnose",
|
||||
"ENABLE_REBAR": "Aktiviere resizable bar in den BIOS-Einstellungen für optimale VR-Performance"
|
||||
},
|
||||
"TUTORIAL": "Tutorial",
|
||||
"RESTART_WAYVR": "WayVR neu starten",
|
||||
"CLOSE_WAYVR": "WayVR schließen",
|
||||
"SPEECH_TO_TEXT": "Sprache zu Text",
|
||||
"WHISPER_GPU_SELECT": "GPU auswählen"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Programmstarter",
|
||||
"APPLICATION_STARTED": "Anwendung gestartet",
|
||||
@@ -264,7 +282,8 @@
|
||||
"SETTINGS": "Audio-Einstellungen",
|
||||
"SPEAKERS": "Lautsprecher",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich eingestellt",
|
||||
"VOLUME": "Lautstärke"
|
||||
"VOLUME": "Lautstärke",
|
||||
"SWITCH_TO_THIS_DEVICE": "Zu diesem Gerät wechseln"
|
||||
},
|
||||
"CLOSE_WINDOW": "Fenster schließen",
|
||||
"CREATION_DATE": "Erstellungsdatum",
|
||||
@@ -349,5 +368,17 @@
|
||||
"ADD_TO_FAVOURITES": "Zu angehefteten Anwendungen hinzufügen",
|
||||
"ADD_TO_FAVOURITES_HINT": "Voreinstellung speichern und an die App-Schublade anheften",
|
||||
"REMOVE_FROM_FAVOURITES": "Aus angehefteten Anwendungen entfernen",
|
||||
"EMPTY": "Leer"
|
||||
"EMPTY": "Leer",
|
||||
"INSTALLED": "Installiert",
|
||||
"NOT_INSTALLED": "Nicht installiert",
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "Energieoptionen",
|
||||
"SHUTDOWN": "Herunterfahren",
|
||||
"SUSPEND": "Ruhezustand",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "Bist du sicher, dass du den Computer ausschalten willst?",
|
||||
"NOT_SUPPORTED": "Energieoptionen erfordern systemd oder elogind.",
|
||||
"SUSPEND_ARE_YOU_SURE": "Bist du sicher, dass du den Computer in den Ruhezustand versetzen willst?"
|
||||
},
|
||||
"YES": "Ja",
|
||||
"NO": "Nein"
|
||||
}
|
||||
@@ -74,6 +74,9 @@ APP_SETTINGS.BINDINGS.ACTION.MOVE_MOUSE,Move mouse (if off by default),Label for
|
||||
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.CHORD,Chord,Label for a group of controller inputs that must all be active together. As in Input Chord
|
||||
APP_SETTINGS.BINDINGS.CHORD_ADD_INPUT,Add chord input,"Button in the controller bindings editor that adds another physical input to a chord. ""Chord"" was previously translated as ""${APP_SETTINGS.BINDINGS.CHORD}""."
|
||||
APP_SETTINGS.BINDINGS.CHORD_INPUT_HAND,Input hand,"Selector for the hand to which we will be binding the input action to."
|
||||
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
|
||||
@@ -119,6 +122,13 @@ 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.DIAGNOSTICS.CPU_ACCESSIBLE_VRAM,"CPU-accessible VRAM: {NUM} MiB","Amount of VRAM accessible by the CPU. For example: 256/4096"
|
||||
APP_SETTINGS.DIAGNOSTICS.TITLE,"Diagnostics","Tab name for the hardware/software check panel"
|
||||
APP_SETTINGS.DIAGNOSTICS.ENABLE_REBAR,"Enable Resizable BAR in the BIOS settings for optimal VR performance","Info shown if resizable bar is disabled in the BIOS. Leave [resizable bar] translation as-is."
|
||||
APP_SETTINGS.DIAGNOSTICS_REASON.PACTL,"Required for speaker/microphone control and audio card switching","Reason for why the given software is recommended"
|
||||
APP_SETTINGS.DIAGNOSTICS_REASON.CAGE,"Recommended in case if there's an incompatibility with some X11 applications (Compatibility mode)","Reason for why the given software is required or recommended"
|
||||
APP_SETTINGS.DIAGNOSTICS_REASON.XWAYLAND_SATELLITE,"Recommended in case if you want to run X11 (Xwayland) applications in native mode","Reason for why the given software is required or recommended"
|
||||
APP_SETTINGS.DIAGNOSTICS_REASON.XDG_OPEN,"Required for opening URLs or Steam games","Reason for why the given software is required or recommended"
|
||||
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)."
|
||||
@@ -143,6 +153,9 @@ APP_SETTINGS.LEFT_HANDED_MOUSE_HELP,Use this if mouse buttons are swapped,Toolti
|
||||
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.MIDDLE_GRABS_SINGLE,"Middle-click modifier grabs individual","Checkbox label in Settings > Controls tab. When enabled, grabbing with the middle modifier will always grab individual objects, never the entire set of objects. ""Middle-click modifier"" was previously translated as ""${APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_MIDDLE}"""
|
||||
APP_SETTINGS.MIDDLE_GRABS_SINGLE_HELP,"Grabbing with the middle-click modifier (purple laser)
|
||||
will grab individual overlays, not the entire set","Tooltip for the middle modifier grabs single overlays checkbox. ""Middle-click modifier"" was previously translated as ""${APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_MIDDLE}"""
|
||||
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.
|
||||
@@ -195,8 +208,8 @@ APP_SETTINGS.SAVE_PLAYSPACE_CENTER,Save playspace center,"Button in Settings > S
|
||||
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.RESTART_WAYVR,Restart WayVR,Button in Settings which restarts WayVR
|
||||
APP_SETTINGS.CLOSE_WAYVR,Close WayVR,Button in Settings which closes WayVR
|
||||
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.
|
||||
@@ -206,7 +219,6 @@ APP_SETTINGS.SNAP_ANGLE_DEG,Window pitch & roll snap angle,Slider in Settings >
|
||||
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}""."
|
||||
@@ -247,6 +259,9 @@ APP_SETTINGS.WHISPER_MODEL,Speech-to-text model,Dropdown label in Settings > Fea
|
||||
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.SPEECH_TO_TEXT,"Speech to text","Category header in Settings"
|
||||
APP_SETTINGS.WHISPER_GPU_SELECT,"Select GPU","A list of GPUs the user can select from"
|
||||
APP_SETTINGS.TUTORIAL,Tutorial,Tooltip for tutorial button in the main screen.
|
||||
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.
|
||||
@@ -255,6 +270,7 @@ APP_SETTINGS.CANCEL,Cancel,Button label in the controller bindings editor popup
|
||||
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.SWITCH_TO_THIS_DEVICE,Switch to this device,Button in the audio settings dialog
|
||||
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.
|
||||
@@ -322,6 +338,12 @@ MODIFICATION_DATE,Modification date,Column label in the remote skymap downloader
|
||||
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.
|
||||
POWER_OPTIONS.TITLE,"Power options","A button which allows the user to perform a specific power action"
|
||||
POWER_OPTIONS.SHUTDOWN,"Shut down","One of the power options: shuts down the computer"
|
||||
POWER_OPTIONS.SUSPEND,"Suspend","One of the power options: suspends the computer"
|
||||
POWER_OPTIONS.NOT_SUPPORTED,"Power options require systemd or elogind.","Notification to the user that power options (shutdown and suspend) are not available. 'systemd' and 'elogind' are package names and should not be translated."
|
||||
POWER_OPTIONS.SHUTDOWN_ARE_YOU_SURE,"Are you sure you want to turn off your computer?","Question dialog box before shutting down the computer"
|
||||
POWER_OPTIONS.SUSPEND_ARE_YOU_SURE,"Are you sure you want to put your computer to sleep?","Question dialog box before putting the computer in sleep mode"
|
||||
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.
|
||||
@@ -341,3 +363,7 @@ ADD_TO_FAVOURITES,Add to pinned apps,"Label on the pin button in the app launche
|
||||
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.
|
||||
INSTALLED,"Installed","Installation flag (installed/not installed)"
|
||||
NOT_INSTALLED,"Not installed","Installation flag (installed/not installed)"
|
||||
YES,"Yes","Just a simple 'Yes' message, button in the dialog box"
|
||||
NO,"No","Just a simple 'No' message, button in the dialog box"
|
||||
|
@@ -95,6 +95,9 @@
|
||||
},
|
||||
"LEFT": "Left",
|
||||
"RIGHT": "Right",
|
||||
"CHORD": "Chord",
|
||||
"CHORD_ADD_INPUT": "Add chord input",
|
||||
"CHORD_INPUT_HAND": "Input hand",
|
||||
"COMPONENT": "Actuation type",
|
||||
"SUBPATH": "Actuating control",
|
||||
"THRESHOLD": "Activate when above upper value\nDeactivate when below lower value"
|
||||
@@ -136,6 +139,17 @@
|
||||
"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.",
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "CPU-accessible VRAM: {NUM} MiB",
|
||||
"TITLE": "Diagnostics",
|
||||
"ENABLE_REBAR": "Enable Resizable BAR in the BIOS settings for optimal VR performance"
|
||||
},
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "Required for speaker/microphone control and audio card switching",
|
||||
"CAGE": "Recommended in case if there's an incompatibility with some X11 applications (Compatibility mode)",
|
||||
"XWAYLAND_SATELLITE": "Recommended in case if you want to run X11 (Xwayland) applications in native mode",
|
||||
"XDG_OPEN": "Required for opening URLs or Steam games"
|
||||
},
|
||||
"HIDE_GRAB_HELP": "Hide grab help",
|
||||
"HIDE_USERNAME": "Hide username",
|
||||
"INPUT_EMULATION_METHOD": "Input emulation method",
|
||||
@@ -156,6 +170,8 @@
|
||||
"LONG_PRESS_DURATION": "Long press duration",
|
||||
"LOOK_AND_FEEL": "Look & Feel",
|
||||
"MISC": "Miscellaneous",
|
||||
"MIDDLE_GRABS_SINGLE": "Middle-click modifier grabs individual",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "Grabbing with the middle-click modifier (purple laser)\nwill grab individual overlays, not the entire set",
|
||||
"NOTIFICATIONS_ENABLED": "Enable notifications",
|
||||
"NOTIFICATIONS_SOUND_ENABLED": "Notification sounds",
|
||||
"NOT_SUPPORTED": "Not supported",
|
||||
@@ -195,8 +211,8 @@
|
||||
"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_HELP": "Apply settings that require a restart",
|
||||
"RESTART_WAYVR": "Restart WayVR",
|
||||
"CLOSE_WAYVR": "Close WayVR",
|
||||
"ROUND_MULTIPLIER": "UI Edge roundness",
|
||||
"SCREEN_RENDER_DOWN": "Render screen at lower resolution",
|
||||
"SCREEN_RENDER_DOWN_HELP": "Helps with aliasing on high-res screens",
|
||||
@@ -206,7 +222,6 @@
|
||||
"SNAP_ANGLE_DEG_HELP": "Grabbed windows snap to this angle on pitch and roll axis.",
|
||||
"ENABLE_WATCH": "Enable watch",
|
||||
"SETS_ON_WATCH": "Sets on watch",
|
||||
"SHOW_WELCOME_SCREEN": "Show welcome screen",
|
||||
"SKYBOX": "Skymap",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
|
||||
"SPACE_DRAG": "Playspace",
|
||||
@@ -243,6 +258,9 @@
|
||||
},
|
||||
"WHISPER_MODEL": "Speech-to-text model",
|
||||
"WHISPER_MODEL_HELP": "Whisper model to use.\nLarger models produce more accurate\nresults, but consume more VRAM.",
|
||||
"SPEECH_TO_TEXT": "Speech to text",
|
||||
"WHISPER_GPU_SELECT": "Select GPU",
|
||||
"TUTORIAL": "Tutorial",
|
||||
"GRID_OPACITY": "Floor grid opacity",
|
||||
"GRID_OPACITY_HELP": "Opacity of the floor grid when the skymap is enabled",
|
||||
"XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default",
|
||||
@@ -253,6 +271,7 @@
|
||||
"APPLICATION_STARTED": "Application started",
|
||||
"APPLICATIONS": "Applications",
|
||||
"AUDIO": {
|
||||
"SWITCH_TO_THIS_DEVICE": "Switch to this device",
|
||||
"AUTO_SWITCH_TO_VR_AUDIO": "Auto-switch to VR audio",
|
||||
"CARDS": "Cards",
|
||||
"FAILED_TO_SWITCH_MICROPHONE": "Failed to switch microphone",
|
||||
@@ -329,6 +348,14 @@
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Resolution"
|
||||
},
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "Power options",
|
||||
"SHUTDOWN": "Shut down",
|
||||
"SUSPEND": "Suspend",
|
||||
"NOT_SUPPORTED": "Power options require systemd or elogind.",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "Are you sure you want to turn off your computer?",
|
||||
"SUSPEND_ARE_YOU_SURE": "Are you sure you want to put your computer to sleep?"
|
||||
},
|
||||
"PROCESS": {
|
||||
"FORCE_KILL": "Force-kill",
|
||||
"STOP": "Stop"
|
||||
@@ -349,5 +376,9 @@
|
||||
"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"
|
||||
"EMPTY": "Empty",
|
||||
"INSTALLED": "Installed",
|
||||
"NOT_INSTALLED": "Not installed",
|
||||
"YES": "Yes",
|
||||
"NO": "No"
|
||||
}
|
||||
@@ -97,7 +97,10 @@
|
||||
"RIGHT": "Derecha",
|
||||
"COMPONENT": "Tipo de accionamiento",
|
||||
"SUBPATH": "Control a accionar",
|
||||
"THRESHOLD": "Activar al superar el valor superior\nDesactivar al caer bajo el valor inferior"
|
||||
"THRESHOLD": "Activar al superar el valor superior\nDesactivar al caer bajo el valor inferior",
|
||||
"CHORD": "Acorde",
|
||||
"CHORD_ADD_INPUT": "Añadir entrada al acorde",
|
||||
"CHORD_INPUT_HAND": "Mano de entrada"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "Explorar catálogo en línea...",
|
||||
"BROWSE_SKYMAPS": "Explorar skymaps",
|
||||
@@ -194,8 +197,6 @@
|
||||
"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",
|
||||
@@ -205,7 +206,6 @@
|
||||
"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",
|
||||
@@ -247,7 +247,25 @@
|
||||
"STATISTICS": "Estadísticas",
|
||||
"ROTATIONS": "Rotaciones del HMD",
|
||||
"SESSION_TIME": "Tiempo de sesión",
|
||||
"LENS_SEPARATION_MM": "Separación de lentes (mm)"
|
||||
"LENS_SEPARATION_MM": "Separación de lentes (mm)",
|
||||
"MIDDLE_GRABS_SINGLE": "El modificador de clic central agarra objetos individuales",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "Al agarrar con el modificador de clic central (láser púrpura),\nse agarrarán overlays individuales y no el set completo",
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "Necesario para el control de altavoces/micrófono y el cambio de tarjeta de audio",
|
||||
"CAGE": "Recomendado en caso de incompatibilidad con algunas aplicaciones X11 (Modo de compatibilidad)",
|
||||
"XWAYLAND_SATELLITE": "Recomendado si quieres ejecutar aplicaciones X11 (Xwayland) en modo nativo",
|
||||
"XDG_OPEN": "Necesario para abrir URLs o juegos de Steam"
|
||||
},
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "VRAM accesible por CPU: {NUM} MiB",
|
||||
"TITLE": "Diagnósticos",
|
||||
"ENABLE_REBAR": "Activa [resizable bar] en la configuración de la BIOS para un rendimiento óptimo de VR"
|
||||
},
|
||||
"TUTORIAL": "Tutorial",
|
||||
"RESTART_WAYVR": "Reiniciar WayVR",
|
||||
"CLOSE_WAYVR": "Cerrar WayVR",
|
||||
"SPEECH_TO_TEXT": "Dictado por voz",
|
||||
"WHISPER_GPU_SELECT": "Seleccionar GPU"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Lanzador de aplicaciones",
|
||||
"APPLICATION_STARTED": "Aplicación iniciada",
|
||||
@@ -264,7 +282,8 @@
|
||||
"SETTINGS": "Ajustes de audio",
|
||||
"SPEAKERS": "Altavoces",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente",
|
||||
"VOLUME": "Volumen"
|
||||
"VOLUME": "Volumen",
|
||||
"SWITCH_TO_THIS_DEVICE": "Cambiar a este dispositivo"
|
||||
},
|
||||
"CLOSE_WINDOW": "Cerrar ventana",
|
||||
"CREATION_DATE": "Fecha de creación",
|
||||
@@ -349,5 +368,17 @@
|
||||
"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"
|
||||
"EMPTY": "Vacío",
|
||||
"INSTALLED": "Instalado",
|
||||
"NOT_INSTALLED": "No instalado",
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "Opciones de energía",
|
||||
"SHUTDOWN": "Apagar",
|
||||
"SUSPEND": "Suspender",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "¿Seguro que quieres apagar el ordenador?",
|
||||
"NOT_SUPPORTED": "Las opciones de energía requieren systemd o elogind.",
|
||||
"SUSPEND_ARE_YOU_SURE": "¿Estás seguro de que quieres suspender el equipo?"
|
||||
},
|
||||
"YES": "Sí",
|
||||
"NO": "No"
|
||||
}
|
||||
@@ -97,7 +97,10 @@
|
||||
"RIGHT": "Destro",
|
||||
"COMPONENT": "Tipo di attuazione",
|
||||
"SUBPATH": "Comando di attivazione",
|
||||
"THRESHOLD": "Attiva sopra il valore superiore\nDisattiva sotto il valore inferiore"
|
||||
"THRESHOLD": "Attiva sopra il valore superiore\nDisattiva sotto il valore inferiore",
|
||||
"CHORD": "Combinazione",
|
||||
"CHORD_ADD_INPUT": "Aggiungi input combinazione",
|
||||
"CHORD_INPUT_HAND": "Mano di input"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "Sfoglia catalogo online...",
|
||||
"BROWSE_SKYMAPS": "Sfoglia skymap",
|
||||
@@ -194,8 +197,6 @@
|
||||
"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",
|
||||
@@ -205,7 +206,6 @@
|
||||
"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",
|
||||
@@ -247,7 +247,25 @@
|
||||
"STATISTICS": "Statistiche",
|
||||
"ROTATIONS": "Rotazioni HMD",
|
||||
"SESSION_TIME": "Tempo sessione",
|
||||
"LENS_SEPARATION_MM": "Distanza lenti (mm)"
|
||||
"LENS_SEPARATION_MM": "Distanza lenti (mm)",
|
||||
"MIDDLE_GRABS_SINGLE": "Il modificatore click centrale afferra singoli oggetti",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "Afferrando con il modificatore click centrale (laser viola),\nsi afferrano i singoli overlay e non l'intero set",
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "Necessario per il controllo di altoparlanti/microfono e il cambio della scheda audio",
|
||||
"CAGE": "Consigliato in caso di incompatibilità con alcune applicazioni X11 (Modalità compatibilità)",
|
||||
"XWAYLAND_SATELLITE": "Consigliato per eseguire applicazioni X11 (Xwayland) in modalità nativa",
|
||||
"XDG_OPEN": "Necessario per aprire URL o giochi Steam"
|
||||
},
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "VRAM accessibile dalla CPU: {NUM} MiB",
|
||||
"TITLE": "Diagnostica",
|
||||
"ENABLE_REBAR": "Abilita Resizable BAR nelle impostazioni del BIOS per prestazioni VR ottimali"
|
||||
},
|
||||
"TUTORIAL": "Tutorial",
|
||||
"RESTART_WAYVR": "Riavvia WayVR",
|
||||
"CLOSE_WAYVR": "Chiudi WayVR",
|
||||
"SPEECH_TO_TEXT": "Speech-to-text",
|
||||
"WHISPER_GPU_SELECT": "Seleziona GPU"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Avvio applicazioni",
|
||||
"APPLICATION_STARTED": "Applicazione avviata",
|
||||
@@ -264,7 +282,8 @@
|
||||
"SETTINGS": "Impostazioni audio",
|
||||
"SPEAKERS": "Altoparlanti",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "Altoparlanti impostati correttamente",
|
||||
"VOLUME": "Volume"
|
||||
"VOLUME": "Volume",
|
||||
"SWITCH_TO_THIS_DEVICE": "Passa a questo dispositivo"
|
||||
},
|
||||
"CLOSE_WINDOW": "Chiudi finestra",
|
||||
"CREATION_DATE": "Data di creazione",
|
||||
@@ -349,5 +368,17 @@
|
||||
"ADD_TO_FAVOURITES": "Aggiungi alle applicazioni fissate",
|
||||
"ADD_TO_FAVOURITES_HINT": "Salva il preset e fissalo al cassetto delle app",
|
||||
"REMOVE_FROM_FAVOURITES": "Rimuovi dalle app fissate",
|
||||
"EMPTY": "Vuoto"
|
||||
"EMPTY": "Vuoto",
|
||||
"INSTALLED": "Installato",
|
||||
"NOT_INSTALLED": "Non installato",
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "Opzioni di alimentazione",
|
||||
"SHUTDOWN": "Spegni",
|
||||
"SUSPEND": "Sospendi",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "Sei sicuro di voler spegnere il computer?",
|
||||
"NOT_SUPPORTED": "Le opzioni di alimentazione richiedono systemd o elogind.",
|
||||
"SUSPEND_ARE_YOU_SURE": "Sei sicuro di voler mettere il computer in sospensione?"
|
||||
},
|
||||
"YES": "Sì",
|
||||
"NO": "No"
|
||||
}
|
||||
@@ -94,10 +94,13 @@
|
||||
"SCROLL": "スクロール*"
|
||||
},
|
||||
"LEFT": "左手",
|
||||
"RIGHT": "右",
|
||||
"RIGHT": "右手",
|
||||
"COMPONENT": "入力形式",
|
||||
"SUBPATH": "操作ボタン",
|
||||
"THRESHOLD": "上の値を超えると有効\n下の値を下回ると無効"
|
||||
"THRESHOLD": "上の値を超えると有効\n下の値を下回ると無効",
|
||||
"CHORD": "コード",
|
||||
"CHORD_ADD_INPUT": "コード入力の追加",
|
||||
"CHORD_INPUT_HAND": "入力側の手"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "オンラインカタログを見る...",
|
||||
"BROWSE_SKYMAPS": "スカイマップを選択",
|
||||
@@ -194,8 +197,6 @@
|
||||
"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": "高解像度ディスプレイでのジャギーを軽減する",
|
||||
@@ -205,7 +206,6 @@
|
||||
"SNAP_ANGLE_DEG_HELP": "掴んでいるウィンドウが、ピッチ軸とロール軸でこの角度にスナップします。",
|
||||
"ENABLE_WATCH": "ウォッチを有効にする",
|
||||
"SETS_ON_WATCH": "ウォッチにセットを表示",
|
||||
"SHOW_WELCOME_SCREEN": "ウェルカムスクリーンを表示",
|
||||
"SKYBOX": "スカイマップ",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "このスカイマップはすでにダウンロード済みです。操作を選択してください。",
|
||||
"SPACE_DRAG": "プレイスペース",
|
||||
@@ -247,7 +247,25 @@
|
||||
"STATISTICS": "統計",
|
||||
"ROTATIONS": "HMD回転数",
|
||||
"SESSION_TIME": "セッション時間",
|
||||
"LENS_SEPARATION_MM": "レンズ間隔 (mm)"
|
||||
"LENS_SEPARATION_MM": "レンズ間隔 (mm)",
|
||||
"MIDDLE_GRABS_SINGLE": "中クリック修飾キーで個別に掴む",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "中クリック修飾キー(紫色のレーザー)で掴むと、\nセット全体ではなく個別のオーバーレイを掴むことができる",
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "スピーカー・マイクの制御およびオーディオカードの切り替えに必要",
|
||||
"CAGE": "一部のX11アプリで互換性問題が発生する場合に推奨(互換モード)",
|
||||
"XWAYLAND_SATELLITE": "X11 (Xwayland) アプリケーションをネイティブモードで動作させたい場合に推奨",
|
||||
"XDG_OPEN": "URLやSteamゲームの起動に必要"
|
||||
},
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "CPUアクセス可能VRAM: {NUM} MiB",
|
||||
"TITLE": "診断",
|
||||
"ENABLE_REBAR": "VRパフォーマンスを最適化するため、BIOS設定でresizable BARを有効にして下さい"
|
||||
},
|
||||
"TUTORIAL": "チュートリアル",
|
||||
"RESTART_WAYVR": "WayVRを再起動",
|
||||
"CLOSE_WAYVR": "WayVRを閉じる",
|
||||
"SPEECH_TO_TEXT": "音声入力",
|
||||
"WHISPER_GPU_SELECT": "GPUを選択"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "アプリランチャー",
|
||||
"APPLICATION_STARTED": "アプリが起動しました",
|
||||
@@ -264,7 +282,8 @@
|
||||
"SETTINGS": "オーディオ設定",
|
||||
"SPEAKERS": "スピーカー",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定完了",
|
||||
"VOLUME": "音量"
|
||||
"VOLUME": "音量",
|
||||
"SWITCH_TO_THIS_DEVICE": "このデバイスに切り替え"
|
||||
},
|
||||
"CLOSE_WINDOW": "ウィンドウを閉じる",
|
||||
"CREATION_DATE": "作成日",
|
||||
@@ -349,5 +368,17 @@
|
||||
"ADD_TO_FAVOURITES": "固定済みアプリに追加",
|
||||
"ADD_TO_FAVOURITES_HINT": "プリセットを保存し、アプリドロワーに固定する",
|
||||
"REMOVE_FROM_FAVOURITES": "固定済みアプリから外す",
|
||||
"EMPTY": "なし"
|
||||
"EMPTY": "なし",
|
||||
"INSTALLED": "インストール済み",
|
||||
"NOT_INSTALLED": "未インストール",
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "電源オプション",
|
||||
"SHUTDOWN": "シャットダウン",
|
||||
"SUSPEND": "サスペンド",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "コンピューターをシャットダウンしてもよろしいですか?",
|
||||
"NOT_SUPPORTED": "電源オプションには systemd または elogind が必要です。",
|
||||
"SUSPEND_ARE_YOU_SURE": "コンピューターをスリープ状態にしますか?"
|
||||
},
|
||||
"YES": "はい",
|
||||
"NO": "いいえ"
|
||||
}
|
||||
@@ -97,7 +97,10 @@
|
||||
"RIGHT": "Prawy",
|
||||
"COMPONENT": "Typ aktywacji",
|
||||
"SUBPATH": "Aktywujący sterownik",
|
||||
"THRESHOLD": "Aktywuj powyżej górnej wartości\nDeaktywuj poniżej dolnej wartości"
|
||||
"THRESHOLD": "Aktywuj powyżej górnej wartości\nDeaktywuj poniżej dolnej wartości",
|
||||
"CHORD": "Akord",
|
||||
"CHORD_ADD_INPUT": "Dodaj wejście do akordu",
|
||||
"CHORD_INPUT_HAND": "Ręka sterująca"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "Przeglądaj katalog online...",
|
||||
"BROWSE_SKYMAPS": "Przeglądaj skymapy",
|
||||
@@ -194,8 +197,6 @@
|
||||
"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",
|
||||
@@ -205,7 +206,6 @@
|
||||
"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",
|
||||
@@ -247,7 +247,25 @@
|
||||
"STATISTICS": "Statystyki",
|
||||
"ROTATIONS": "Obroty HMD",
|
||||
"SESSION_TIME": "Czas sesji",
|
||||
"LENS_SEPARATION_MM": "Rozstaw soczewek (mm)"
|
||||
"LENS_SEPARATION_MM": "Rozstaw soczewek (mm)",
|
||||
"MIDDLE_GRABS_SINGLE": "Modyfikator środkowego przycisku chwyta pojedyncze obiekty",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "Chwytanie z modyfikatorem środkowego przycisku myszy (fioletowy laser)\npochwyci pojedyncze nakładki, a nie cały zestaw",
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "Wymagane do sterowania głośnikami/mikrofonem i przełączania kart dźwiękowych",
|
||||
"CAGE": "Zalecane w przypadku niekompatybilności z niektórymi aplikacjami X11 (tryb kompatybilności)",
|
||||
"XWAYLAND_SATELLITE": "Zalecane, jeśli chcesz uruchamiać aplikacje X11 (Xwayland) w trybie natywnym",
|
||||
"XDG_OPEN": "Wymagane do otwierania linków URL lub gier Steam"
|
||||
},
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "VRAM dostępny dla CPU: {NUM} MiB",
|
||||
"TITLE": "Diagnostyka",
|
||||
"ENABLE_REBAR": "Włącz resizable BAR w ustawieniach BIOS, aby uzyskać optymalną wydajność VR"
|
||||
},
|
||||
"TUTORIAL": "Samouczek",
|
||||
"RESTART_WAYVR": "Zrestartuj WayVR",
|
||||
"CLOSE_WAYVR": "Zamknij WayVR",
|
||||
"SPEECH_TO_TEXT": "Zamiana mowy na tekst",
|
||||
"WHISPER_GPU_SELECT": "Wybierz GPU"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Launcher aplikacji",
|
||||
"APPLICATION_STARTED": "Uruchomiono aplikację",
|
||||
@@ -264,7 +282,8 @@
|
||||
"SETTINGS": "Ustawienia dźwięku",
|
||||
"SPEAKERS": "Głośniki",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "Głośniki ustawione pomyślnie",
|
||||
"VOLUME": "Głośność"
|
||||
"VOLUME": "Głośność",
|
||||
"SWITCH_TO_THIS_DEVICE": "Przełącz na to urządzenie"
|
||||
},
|
||||
"CLOSE_WINDOW": "Zamknij okno",
|
||||
"CREATION_DATE": "Data utworzenia",
|
||||
@@ -349,5 +368,17 @@
|
||||
"ADD_TO_FAVOURITES": "Przypnij aplikację",
|
||||
"ADD_TO_FAVOURITES_HINT": "Zapisz preset i przypnij go do szuflady aplikacji",
|
||||
"REMOVE_FROM_FAVOURITES": "Usuń z przypiętych aplikacji",
|
||||
"EMPTY": "Puste"
|
||||
"EMPTY": "Puste",
|
||||
"INSTALLED": "Zainstalowano",
|
||||
"NOT_INSTALLED": "Nie zainstalowano",
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "Opcje zasilania",
|
||||
"SHUTDOWN": "Wyłącz",
|
||||
"SUSPEND": "Uśpij",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "Czy na pewno chcesz wyłączyć komputer?",
|
||||
"NOT_SUPPORTED": "Opcje zasilania wymagają systemd lub elogind.",
|
||||
"SUSPEND_ARE_YOU_SURE": "Czy na pewno chcesz uśpić komputer?"
|
||||
},
|
||||
"YES": "Tak",
|
||||
"NO": "Nie"
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
{
|
||||
"DEFINITIONS": {
|
||||
"ANCHORED": "Förankrad",
|
||||
"FLOATING": "Flytande",
|
||||
"STATIC": "Stationär",
|
||||
"SET": "Set",
|
||||
"WATCH": "Klocka",
|
||||
"DASHBOARD": "Kontrollpanel",
|
||||
"EDIT_MODE": "Redigeringsläge",
|
||||
"SETTINGS": "Inställningar",
|
||||
"KEYBOARD": "Tangentbord",
|
||||
"TASKBAR": "Uppgiftsfält",
|
||||
"FEATURES": "Funktioner",
|
||||
"OVERLAY": "Overlay",
|
||||
"SKYMAP": "Skymap",
|
||||
"PLAYSPACE": "Playspace",
|
||||
"D_PAD": "D-pad"
|
||||
},
|
||||
"ACTIONS": {
|
||||
"RECENTER_PLAYSPACE": "Centrera om playspace"
|
||||
},
|
||||
"APP_LAUNCHER": {
|
||||
"ASPECT": {
|
||||
"SEMI_TALL": "Halvhög",
|
||||
"SEMI_WIDE": "Halvbredd",
|
||||
"SQUARE": "Kvadratisk",
|
||||
"TALL": "Hög",
|
||||
"WIDE": "Bredbild"
|
||||
},
|
||||
"ASPECT_TITLE": "Bildförhållande",
|
||||
"AUTOSTART": "Kör automatiskt vid start",
|
||||
"LAUNCH": "Starta",
|
||||
"MODE": {
|
||||
"CAGE": "Kompatibilitetsläge (Cage)",
|
||||
"NATIVE": "Nativt läge"
|
||||
},
|
||||
"RES_TITLE": "Upplösning"
|
||||
},
|
||||
"APP_SETTINGS": {
|
||||
"ALLOW_SLIDING": "Stick-interaktion vid grepp",
|
||||
"ANIMATION_SPEED": "Hastighet för UI-animationer",
|
||||
"AUTOSTART_APPS": "Appar som ska köras vid start",
|
||||
"BLOCK_GAME_INPUT": "Blockera spelindata",
|
||||
"BLOCK_GAME_INPUT_HELP": "Blockerar all input när en overlay hovras över",
|
||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignorera klockan vid blockering av input",
|
||||
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Blockera inte inmatning när klockan är markerad",
|
||||
"BLOCK_POSES_ON_KBD_INTERACTION": "Blockera poser vid interaktion med tangentbord",
|
||||
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blockerar spelets mottagning av poser när tangentbordet hovras över och 'Blockera spel-input' är aktiverat",
|
||||
"BINDINGS": {
|
||||
"COMP": {
|
||||
"CLICK": "Klick",
|
||||
"FORCE": "Tryckkraft",
|
||||
"TOUCH": "Beröring",
|
||||
"VALUE": "Värde",
|
||||
"PROXIMITY": "Närhet",
|
||||
"X_AXIS": "X-axel",
|
||||
"Y_AXIS": "Y-axel"
|
||||
},
|
||||
"TYPE": {
|
||||
"BUMPER": "Bumper",
|
||||
"DPAD_UP": "D-pad upp",
|
||||
"DPAD_DOWN": "D-pad ned",
|
||||
"DPAD_LEFT": "D-pad vänster",
|
||||
"DPAD_RIGHT": "D-pad höger",
|
||||
"JOYSTICK": "Joystick",
|
||||
"MENU": "Meny",
|
||||
"SHOULDER": "Axel",
|
||||
"SQUEEZE": "Grepp",
|
||||
"SYSTEM": "System",
|
||||
"THUMBREST": "Tumstöd",
|
||||
"THUMBSTICK": "Thumbstick",
|
||||
"TRACKPAD": "Trackpad",
|
||||
"TRIGGER": "Trigger",
|
||||
"VIEW": "Visa"
|
||||
},
|
||||
"CLICK": {
|
||||
"ANY": "Vilken som helst",
|
||||
"DOUBLE": "Dubbelklicka",
|
||||
"TRIPLE": "Trippelklick",
|
||||
"TYPE": "Antal tryck"
|
||||
},
|
||||
"ACTION": {
|
||||
"CLICK": "Klicka*",
|
||||
"GRAB": "Greppa*",
|
||||
"ALT_CLICK": "Anpassat shell-kommando (ställ in alt_click i config)",
|
||||
"SHOW_HIDE": "Visa, dölj, centrera om*",
|
||||
"TOGGLE_DASHBOARD": "Växla instrumentpanel",
|
||||
"SPACE_DRAG": "Dra playspace",
|
||||
"SPACE_ROTATE": "Rotera playspace",
|
||||
"SPACE_RESET": "Återställ Playspace",
|
||||
"CLICK_MODIFIER_RIGHT": "Högerklick-modifierare",
|
||||
"CLICK_MODIFIER_MIDDLE": "Modifierare för mittklick",
|
||||
"MOVE_MOUSE": "Flytta mus (om avstängd som standard)",
|
||||
"SCROLL": "Scrolla*"
|
||||
},
|
||||
"LEFT": "Vänster",
|
||||
"RIGHT": "Höger",
|
||||
"CHORD": "Kombination",
|
||||
"CHORD_ADD_INPUT": "Lägg till inmatning för kombination",
|
||||
"CHORD_INPUT_HAND": "Inmatningshand",
|
||||
"COMPONENT": "Aktiveringstyp",
|
||||
"SUBPATH": "Aktiverande kontroll",
|
||||
"THRESHOLD": "Aktivera vid övre värdet\nAvaktivera vid nedre värdet"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "Bläddra i onlinekatalogen...",
|
||||
"BROWSE_SKYMAPS": "Bläddra bland skymaps",
|
||||
"CAPTURE_METHOD": "Metod för skärmavbildning",
|
||||
"CAPTURE_METHOD_HELP": "Prova att ändra detta om du\nupplever svarta eller glitchiga skärmar",
|
||||
"COLOR_KEYING": "Färgnyckelning",
|
||||
"COLOR_PALETTE": "Färgpalett",
|
||||
"COLOR_PALETTE_HELP": "Klicka för att bläddra bland färgpaletter.\nSe webbplatsen för att skapa egna!",
|
||||
"COLOR_PALETTES": "Färgpaletter",
|
||||
"COLOR_PALETTE_CURRENT": "Nuvarande aktivt tema.",
|
||||
"COLOR_PALETTE_CUSTOM_URL": "Lägg till ett eget anpassat tema!",
|
||||
"COLOR_PALETTE_CUSTOM_URL2": "Klicka för att öppna webbmanualen.",
|
||||
"COLOR_PALETTE_ACTIVATE": "Klicka för att använda detta tema.",
|
||||
"CLEAR_PIPEWIRE_TOKENS": "Rensa PipeWire-tokens",
|
||||
"CLEAR_PIPEWIRE_TOKENS_HELP": "Fråga om skärmval vid nästa start",
|
||||
"CLEAR_SAVED_STATE": "Återställ sparade inställningar",
|
||||
"CLEAR_SAVED_STATE_HELP": "Återställ sets och overlay-positioner",
|
||||
"CLICK_FREEZE_TIME_MS": "Klickfrysningstid (ms)",
|
||||
"CLICK_FREEZE_TIME_MS_HELP": "Hjälper till med precision vid dubbelklick",
|
||||
"CLOCK_12H": "12-timmarsklocka",
|
||||
"CONTROLS": "Kontroller",
|
||||
"DELETE_ALL_CONFIGS": "Rensa konfiguration",
|
||||
"DELETE_ALL_CONFIGS_HELP": "Ta bort alla konfigurationsfiler från conf.d",
|
||||
"DOUBLE_CURSOR_FIX": "Fix för dubbla markörer",
|
||||
"DOUBLE_CURSOR_FIX_HELP": "Aktivera om du ser två markörer",
|
||||
"DEFAULT_OVERLAY_SCALE": "Standardstorlek för overlay",
|
||||
"DEFAULT_OVERLAY_SCALE_HELP": "Skapa nya overlays i den här skalan.",
|
||||
"DEFAULT_CURVATURE": "Standardkurvatur för overlay",
|
||||
"DEFAULT_OPACITY": "Standardopacitet för overlay",
|
||||
"DEFAULT_POSITIONING": "Standardposition för overlay",
|
||||
"OVERLAY_DEFAULTS_HELP": "Gäller endast nya overlays",
|
||||
"ENABLED": "Aktiverad",
|
||||
"FEATURES": "Funktioner",
|
||||
"FOCUS_FOLLOWS_MOUSE_MODE": "Musrörelse vid trigger-tryck",
|
||||
"HANDSFREE_POINTER": "Handsfree-läge",
|
||||
"HANDSFREE_POINTER_HELP": "Inmatning som används när rörelsekontroller saknas.\nVänster nyp är greppa, höger är klicka.",
|
||||
"HANDSFREE_ALT_TAB": "Sikte för app-växlare",
|
||||
"HANDSFREE_ALT_TAB_HELP": "Håll in Super+X, sikta på önskat fönster och släpp sedan för att byta fokus.",
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "CPU-tillgängligt VRAM: {NUM} MiB",
|
||||
"TITLE": "Diagnostik",
|
||||
"ENABLE_REBAR": "Aktivera [resizable bar] i BIOS-inställningarna för optimal VR-prestanda"
|
||||
},
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "Krävs för kontroll av högtalare/mikrofon och byte av ljudkort",
|
||||
"CAGE": "Rekommenderas vid inkompatibilitet med vissa X11-applikationer (kompatibilitetsläge)",
|
||||
"XWAYLAND_SATELLITE": "Rekommenderas om du vill köra X11 (Xwayland)-applikationer i nativt läge",
|
||||
"XDG_OPEN": "Krävs för att öppna URL:er eller Steam-spel"
|
||||
},
|
||||
"HIDE_GRAB_HELP": "Dölj grepphjälp",
|
||||
"HIDE_USERNAME": "Dölj användarnamn",
|
||||
"INPUT_EMULATION_METHOD": "Metod för inmatningssimulering",
|
||||
"INPUT_EMULATION_METHOD_HELP": "Prova att ändra detta om mus- eller\ntangentbordindata inte registreras.",
|
||||
"INPUT_CAPTURE_METHOD": "Metod för inmatningsfångst",
|
||||
"INPUT_CAPTURE_METHOD_HELP": "Möjliggör användning av fysisk kringutrustning i WayVR.\n Super+Z: Växla input mellan WayVR och skrivbordet\n Super+X: Växla mellan WayVR-appar",
|
||||
"INPUT_PROFILES": "Ändra styrinställningar",
|
||||
"INPUT_PROFILES_HELP": "OpenXR-kontrollbindningar",
|
||||
"INVERT_SCROLL_DIRECTION_X": "Invertera horisontell scrollriktning",
|
||||
"INVERT_SCROLL_DIRECTION_Y": "Invertera vertikal rullningsriktning",
|
||||
"LENS_SEPARATION_MM": "Linsavstånd (mm)",
|
||||
"KEYBOARD_MIDDLE_CLICK": "Tangentbordets mittklick",
|
||||
"KEYBOARD_MIDDLE_CLICK_HELP": "Modifier som används vid skrivning\nmed lila laser",
|
||||
"KEYBOARD_SOUND_ENABLED": "Tangentbordsljud",
|
||||
"LANGUAGE": "Språk",
|
||||
"LEFT_HANDED_MOUSE": "Vänstermus",
|
||||
"LEFT_HANDED_MOUSE_HELP": "Används om musknapparna är ombytta",
|
||||
"LONG_PRESS_DURATION": "Långtryckstid",
|
||||
"LOOK_AND_FEEL": "Utseende och känsla",
|
||||
"MISC": "Övrigt",
|
||||
"MIDDLE_GRABS_SINGLE": "Modifierare för mittklick greppar enskilda objekt",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "Att greppa med modifieraren för mittklick (lila laser)\ngreppar enskilda overlays istället för hela setet",
|
||||
"NOTIFICATIONS_ENABLED": "Aktivera aviseringar",
|
||||
"NOTIFICATIONS_SOUND_ENABLED": "Ljud för aviseringar",
|
||||
"NOT_SUPPORTED": "Ej stöds",
|
||||
"NO_SKYMAPS_FOUND": "Inga skymaps hittades",
|
||||
"OPAQUE_BACKGROUND": "Opak bakgrund",
|
||||
"OPTION": {
|
||||
"ANCHORED_HELP": "Följer centermarkören. Rekommenderas.",
|
||||
"FLOATING_HELP": "Flyttas oberoende, centreras om.\nLätt att tappa bort; rekommenderas ej.",
|
||||
"STATIC_HELP": "Håller sig på plats i förhållande till världen.",
|
||||
"AUTO": "Automatisk",
|
||||
"AUTO_HELP": "ScreenCopy GPU om det stöds,\nannars PipeWire GPU.",
|
||||
"EYE_ONLY": "Ögonlaser",
|
||||
"EYE_PINCH": "Öga + pinch",
|
||||
"HMD_ONLY": "HMD-laser",
|
||||
"HMD_PINCH": "HMD + pinch",
|
||||
"NONE": "Ingen",
|
||||
"NONE_INPUT_HELP": "Emulera inte mus och tangentbord.\nInteraktion med skärmar blir inte möjlig.",
|
||||
"NONE_INPUT_CAPTURE_HELP": "Fånga inte mus och tangentbord.\nDu kommer inte att kunna använda fysisk mus\neller tangentbord i appar som startas i WayVR.",
|
||||
"PIPEWIRE_HELP": "Snabb GPU-avbildning,\nstandard för alla skrivbord.",
|
||||
"PW_FALLBACK_HELP": "Långsam metod med hög CPU-belastning.\nProva om PipeWire GPU inte fungerar",
|
||||
"SCREENCOPY_GPU_HELP": "Snabb, inga popup-fönster för skärmdelning.\nFungerar på: Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "Långsam, inga popup-fönster för skärmdelning.\nFungerar på: Hyprland, Niri, River, Sway",
|
||||
"UINPUT": "Enhetsemulering",
|
||||
"UINPUT_HELP": "Använder modulen uinput för att emulera en enhet.\nFungerar generellt bra på de flesta skrivbord.",
|
||||
"EVDEV_HELP": "Ta kontroll över inmatningsenheter för exklusiv användning.\nAnvändaren måste tillhöra gruppen 'input'.",
|
||||
"WL_VIRTUAL": "Wayland virtuell inmatning",
|
||||
"WL_VIRTUAL_HELP": "Skickar händelser till Wayland-kompositorn via\nzwlr_virtual_pointer och zwp_virtual_keyboard.\nFungerar endast på vissa skrivbord.\nFungerar INTE på KDE, GNOME eller COSMIC."
|
||||
},
|
||||
"POINTER_ACCELERATION": "Musacceleration",
|
||||
"POINTER_ACCELERATION_HELP": "På: Adaptiv musacceleration\nAv: Konstant hastighet",
|
||||
"POINTER_LERP_FACTOR": "Utjämning av pekare",
|
||||
"POINTER_SPEED": "Mushastighet",
|
||||
"REQUIRES_RESTART": "Kräver omstart",
|
||||
"RESET_PLAYSPACE": "Återställ playspace",
|
||||
"RESET_PLAYSPACE_HELP": "Nollställ offset för playspace.",
|
||||
"SAVE_PLAYSPACE_CENTER": "Spara playspace-center",
|
||||
"SAVE_PLAYSPACE_CENTER_HELP": "Använd nuvarande playspace för bindningen \"återställ playspace\".",
|
||||
"RESET_PLAYSPACE_CENTER": "Återställ playspace-center",
|
||||
"RESET_PLAYSPACE_CENTER_HELP": "Rensa tidigare inställd mittpunkt för playspace.",
|
||||
"RESTART_WAYVR": "Starta om WayVR",
|
||||
"CLOSE_WAYVR": "Stäng WayVR",
|
||||
"ROUND_MULTIPLIER": "UI-kanternas rundning",
|
||||
"SCREEN_RENDER_DOWN": "Rendera skärm i lägre upplösning",
|
||||
"SCREEN_RENDER_DOWN_HELP": "Hjälper mot aliasing på skärmar med hög upplösning",
|
||||
"SCROLL_SPEED": "Scrollningshastighet",
|
||||
"SELECT_VARIANT": "Välj variant",
|
||||
"SNAP_ANGLE_DEG": "Snapvinkel för fönster (pitch & roll)",
|
||||
"SNAP_ANGLE_DEG_HELP": "Greppade fönster snäpps till denna vinkel på pitch- och rollaxeln.",
|
||||
"ENABLE_WATCH": "Aktivera klockan",
|
||||
"SETS_ON_WATCH": "Set på klockan",
|
||||
"SKYBOX": "Skymap",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "Denna skymap är redan nedladdad. Välj åtgärd.",
|
||||
"SPACE_DRAG": "Playspace",
|
||||
"SPACE_DRAG_MULTIPLIER": "Multiplikator för space-drag",
|
||||
"SPACE_DRAG_AFFECTS_WORLD": "Lämna overlays kvar vid flytt av playspace",
|
||||
"SPACE_DRAG_UNLOCKED": "Tillåt space-drag på alla axlar",
|
||||
"SPACE_GRAVITY_DAMPING": "Dämpning",
|
||||
"SPACE_GRAVITY_DAMPING_HELP": "Artificiell dämpning för att sakta ner rörelser. 0,1 – hög dämpning, 1,0 – ingen dämpning",
|
||||
"SPACE_GRAVITY_FLING_STRENGTH": "Kaststyrka",
|
||||
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Intensitetsmultiplikator för gravitationskraften efter space-drag.\n0.0 - ingen rörelse alls, 2.0 - dubbel intensitet",
|
||||
"SPACE_GRAVITY_GRAVITY": "Gravitation",
|
||||
"SPACE_GRAVITY_GRAVITY_HELP": "Mängd nedåtgående kraft. 0.0 - ingen gravitation",
|
||||
"SPACE_GRAVITY_GROUND_FRICTION": "Markfriktion",
|
||||
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Mängden friktion som saktar ner dig när du rör vid marken.\n0.0 - ingen friktion (som på is), 1.0 - sträv yta",
|
||||
"SPACE_GRAVITY_FLOOR_HEIGHT": "Golvhöjd",
|
||||
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Y-positionen för golvet. Gravitationen upphör när denna höjd nås.",
|
||||
"SPACE_ROTATE_UNLOCKED": "Tillåt rotation av playspace på alla axlar",
|
||||
"ROTATIONS": "HMD-rotationer",
|
||||
"SESSION_TIME": "Sessionstid",
|
||||
"STATISTICS": "Statistik",
|
||||
"TROUBLESHOOTING": "Felsökning",
|
||||
"UI_GRADIENT_INTENSITY": "Intensitet för UI-gradient",
|
||||
"UPRIGHT_SCREEN_FIX": "Fix för upprätt skärm",
|
||||
"UPRIGHT_SCREEN_FIX_HELP": "Fixar upprätt ställda skärmar på vissa skrivbord",
|
||||
"USE_PASSTHROUGH": "Aktivera passthrough",
|
||||
"USE_PASSTHROUGH_HELP": "Tillåt passthrough om XR-runtime stöder det",
|
||||
"USE_SKYBOX": "Visa skymap",
|
||||
"USE_SKYBOX_HELP": "Visa en skymap om ingen scenapp eller passthrough används",
|
||||
"WATCH_VIEW_ANGLE": "Klockans synvinklar",
|
||||
"WATCH_VIEW_ANGLE_HELP": "Styr hur klockan tonas ut",
|
||||
"WHISPER": {
|
||||
"NEED_TO_DOWNLOAD_MODEL": "Den valda modellen måste laddas ner.\nVill du ladda ner den nu?",
|
||||
"REMOVE_UNUSED_MODELS": "Du stänger av tal-till-text-funktionen.\nVill du ta bort nedladdade Whisper-modeller för att frigöra utrymme?"
|
||||
},
|
||||
"WHISPER_MODEL": "Tal-till-text-modell",
|
||||
"WHISPER_MODEL_HELP": "Whisper-modell som ska användas.\nStörre modeller ger mer precisa\nresultat, men förbrukar mer VRAM.",
|
||||
"SPEECH_TO_TEXT": "Tal till text",
|
||||
"WHISPER_GPU_SELECT": "Välj GPU",
|
||||
"TUTORIAL": "Handbok",
|
||||
"GRID_OPACITY": "Golvgridens opacitet",
|
||||
"GRID_OPACITY_HELP": "Opacitet för golvgridet när skymap är aktiverat",
|
||||
"XWAYLAND_BY_DEFAULT": "Kör appar i kompatibilitetsläge som standard",
|
||||
"SAVE": "Spara",
|
||||
"CANCEL": "Avbryt"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "App-startare",
|
||||
"APPLICATION_STARTED": "Applikationen startades",
|
||||
"APPLICATIONS": "Applikationer",
|
||||
"AUDIO": {
|
||||
"SWITCH_TO_THIS_DEVICE": "Byt till den här enheten",
|
||||
"AUTO_SWITCH_TO_VR_AUDIO": "Byt automatiskt till VR-ljud",
|
||||
"CARDS": "Kort",
|
||||
"FAILED_TO_SWITCH_MICROPHONE": "Kunde inte byta mikrofon",
|
||||
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofonen har ändrats",
|
||||
"MICROPHONES": "Mikrofoner",
|
||||
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Ingen VR-mikrofon hittades. Byt manuellt.",
|
||||
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Inga VR-högtalare hittades. Byt manuellt.",
|
||||
"SELECT_AUDIO_CARD_PROFILE": "Välj ljudkortsprofil",
|
||||
"SETTINGS": "Ljudinställningar",
|
||||
"SPEAKERS": "Högtalare",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "Högtalarna har ändrats",
|
||||
"VOLUME": "Volym"
|
||||
},
|
||||
"CLOSE_WINDOW": "Stäng fönster",
|
||||
"CREATION_DATE": "Skapad datum",
|
||||
"DEBUG_INFO": "Debuginfo",
|
||||
"DISPLAY_BRIGHTNESS": "Skärmljusstyrka",
|
||||
"DONATE": {
|
||||
"SUPPORT_US": "Stöd oss",
|
||||
"DESCRIPTION": "Vi är ett litet team på två utvecklare som bygger WayVR på vår fritid. Om du gillar att använda programvaran, överväg att stötta oss – varje donation hjälper oss att fortsätta.",
|
||||
"THANK_YOU_WAYVR": "Tack från WayVR-teamet!",
|
||||
"BUTTON_TOOLTIP": "Donera via Open Collective",
|
||||
"CURRENT_SUPPORTERS": "Nuvarande supportrar",
|
||||
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Stöds av {USER}|Särskilt tack till {USER}|Sponsras av {USER}|Backas av {USER}|Drivs av community-medlemmar som {USER}|Möjliggjorts av {USER}|Upprätthålls av {USER}|Bidrag från {USER}|Finansierat av {USER}",
|
||||
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kaffe sponsrat av {USER}|Drivs av {USER}|Hälsningar till {USER}!|Håller oss igång: {USER}|Hjälper oss att växa: {USER}|Håller servrarna igång: {USER}|Med tacksamhet till {USER}|Drivs av {USER}|Stöds av vänner som {USER}",
|
||||
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Stöttas av legender som {USER}|Koffein sponsrat av {USER}|En sann legend: {USER}|Dagens hjälte: {USER}|En total superstjärna: {USER}|Betalar elräkningen: {USER}|Räddaren av vårt förstånd: {USER}|Visar vägen: {USER}|Koffein-till-kod-omvandlare tillhandahållen av {USER}|Håller produktionen stabil: {USER}|Den ende och ende: {USER}|Skickar dmabuf-buffertar: {USER}"
|
||||
},
|
||||
"DOWNLOAD": "Ladda ner",
|
||||
"DOWNLOADER": "Nedladdare",
|
||||
"WELCOME": {
|
||||
"ALL_SET": "Nu är du redo!",
|
||||
"BASICS": "Dessa grunder gör att du enkelt kan börja använda WayVR.",
|
||||
"CENTER_MARKER": "Centreringsmarkören visas framför dig vid omcentrering. Placera overlays runt den!",
|
||||
"DOUBLE_PRESS_TO_TOGGLE": "Dubbeltryck B (på Index) eller Y (på Meta) för att visa, centrera om eller dölja ditt set. Prova nu.",
|
||||
"FEATURES_DOCUMENTATION": "Det finns många andra funktioner värda att anpassa. För mer information, se dokumentationen på",
|
||||
"FINISH_TUTORIAL": "Avsluta handledningen",
|
||||
"GRAB_BOTH_HANDS": "Greppa med båda händerna om du vill flytta ett specifikt overlay i ditt set.",
|
||||
"GRAB_ONE_HAND": "Greppa med en hand för att flytta ditt set.",
|
||||
"GREETING": "Hej!",
|
||||
"GUIDE_INTRO": "Låt oss guida dig genom dina första steg.",
|
||||
"LASER_COLORS": "Laserfärger",
|
||||
"LASER_FUNCTIONALITY": "Mycket av funktionaliteten i WayVR beror på vilken laserfärg som används för att interagera med ett UI-element. Du behöver inte trycka på knapparna, det räcker att röra vid dem!",
|
||||
"LAST_PAGE_INFO": "Denna handledning slutar visas när du når den sista sidan.",
|
||||
"LOOK_AT_LEFT_WRIST": "Titta på din vänstra handled. Det är din klocka.",
|
||||
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Mittenklick-läge: Lila laser",
|
||||
"MOVING_YOUR_SET": "Flytta ditt set",
|
||||
"NEXT_BUTTON": "Tryck på nästa-knappen nedan för att komma igång.",
|
||||
"REGULAR_MODE_BLUE_LASER": "Vanligt läge: Blå laser",
|
||||
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Flytta det här fönstret med kontrollens grip-funktion.",
|
||||
"RIGHT_CLICK_MODE_ORANGE_LASER": "Högerklicksläge: Orange laser",
|
||||
"THANKS_FOR_INSTALLING": "Tack för att du installerade WayVR!",
|
||||
"WATCH": "Klocka",
|
||||
"WORKING_SET": "Aktivt Set"
|
||||
},
|
||||
"DOWNLOAD_AGAIN": "Ladda ner igen",
|
||||
"DOWNLOADING_FILE": "Laddar ner fil...",
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "Kunde inte starta applikationen:",
|
||||
"GAME_LAUNCHED": "Spelet har startats",
|
||||
"GAME_LIST": {
|
||||
"NO_GAMES_FOUND": "Inga spel hittades",
|
||||
"RUNNING_GAMES_LIST": "Lista över körande spel"
|
||||
},
|
||||
"GAMES": "Spel",
|
||||
"GENERAL_SETTINGS": "Allmänna inställningar",
|
||||
"GETTING_STARTED": "Kom igång",
|
||||
"HEIGHT": "Höjd",
|
||||
"HELLO": "Hej!",
|
||||
"HELLO_USER": "Hej, {USER}!",
|
||||
"HIDE": "Dölj",
|
||||
"HOME_SCREEN": "Hem",
|
||||
"MODIFICATION_DATE": "Ändringsdatum",
|
||||
"MONADO_RUNTIME": "Monado runtime",
|
||||
"LOADING": "Laddar...",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Upplösning"
|
||||
},
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "Strömalternativ",
|
||||
"SHUTDOWN": "Stäng av",
|
||||
"SUSPEND": "Viloläge",
|
||||
"NOT_SUPPORTED": "Strömalternativ kräver systemd eller elogind.",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "Är du säker på att du vill stänga av datorn?",
|
||||
"SUSPEND_ARE_YOU_SURE": "Är du säker på att du vill försätta datorn i viloläge?"
|
||||
},
|
||||
"PROCESS": {
|
||||
"FORCE_KILL": "Tvinga avslut",
|
||||
"STOP": "Stoppa"
|
||||
},
|
||||
"PROCESS_LIST": "Processlista",
|
||||
"REFRESH": "Uppdatera",
|
||||
"REMOVE": "Ta bort",
|
||||
"APPLY": "Verkställ",
|
||||
"RELOAD_FROM_DISK": "Ladda om från disk",
|
||||
"SETTINGS": "Inställningar",
|
||||
"SHOW": "Visa",
|
||||
"TARGET_PATH": "Mål sökväg",
|
||||
"TERMINATE_PROCESS": "Avsluta process",
|
||||
"VERSION": "Version",
|
||||
"WIDTH": "Bredd",
|
||||
"PINNED_APPS": "Fästa applikationer",
|
||||
"SAVED_TO_FAVOURITES": "Sparad i fästa applikationer",
|
||||
"ADD_TO_FAVOURITES": "Lägg till i fästa applikationer",
|
||||
"ADD_TO_FAVOURITES_HINT": "Spara förinställning och fäst den i app-menyn",
|
||||
"REMOVE_FROM_FAVOURITES": "Ta bort från fästa applikationer",
|
||||
"EMPTY": "Tomt",
|
||||
"INSTALLED": "Installerad",
|
||||
"NOT_INSTALLED": "Ej installerad",
|
||||
"YES": "Ja",
|
||||
"NO": "Nej"
|
||||
}
|
||||
@@ -97,7 +97,10 @@
|
||||
"RIGHT": "右侧",
|
||||
"COMPONENT": "触发类型",
|
||||
"SUBPATH": "激活控件",
|
||||
"THRESHOLD": "高于上限值时激活\n低于下限值时取消激活"
|
||||
"THRESHOLD": "高于上限值时激活\n低于下限值时取消激活",
|
||||
"CHORD": "组合键",
|
||||
"CHORD_ADD_INPUT": "添加组合键输入",
|
||||
"CHORD_INPUT_HAND": "输入手"
|
||||
},
|
||||
"BROWSE_ONLINE_CATALOG": "浏览在线目录...",
|
||||
"BROWSE_SKYMAPS": "浏览天空盒",
|
||||
@@ -194,8 +197,6 @@
|
||||
"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": "有助于减轻高分辨率屏幕上的锯齿现象",
|
||||
@@ -205,7 +206,6 @@
|
||||
"SNAP_ANGLE_DEG_HELP": "抓取窗口在俯仰轴和翻滚轴上按此角度对齐。",
|
||||
"ENABLE_WATCH": "启用手表",
|
||||
"SETS_ON_WATCH": "手表显示套装",
|
||||
"SHOW_WELCOME_SCREEN": "显示欢迎界面",
|
||||
"SKYBOX": "天空图",
|
||||
"SKYMAP_ALREADY_DOWNLOADED": "此天空盒已下载。请选择操作。",
|
||||
"SPACE_DRAG": "活动空间",
|
||||
@@ -247,7 +247,25 @@
|
||||
"STATISTICS": "统计数据",
|
||||
"ROTATIONS": "HMD 旋转次数",
|
||||
"SESSION_TIME": "会话时间",
|
||||
"LENS_SEPARATION_MM": "瞳距 (mm)"
|
||||
"LENS_SEPARATION_MM": "瞳距 (mm)",
|
||||
"MIDDLE_GRABS_SINGLE": "中键点击修饰键抓取单个对象",
|
||||
"MIDDLE_GRABS_SINGLE_HELP": "使用中键点击修饰键(紫色激光)抓取时\n将抓取单个叠加层,而非整个集合",
|
||||
"DIAGNOSTICS_REASON": {
|
||||
"PACTL": "用于扬声器/麦克风控制及声卡切换",
|
||||
"CAGE": "若部分 X11 应用程序不兼容,建议开启(兼容模式)",
|
||||
"XWAYLAND_SATELLITE": "如果你想以原生模式运行 X11 (Xwayland) 应用程序,建议开启此项",
|
||||
"XDG_OPEN": "打开 URL 或 Steam 游戏所需"
|
||||
},
|
||||
"DIAGNOSTICS": {
|
||||
"CPU_ACCESSIBLE_VRAM": "CPU 可访问 VRAM: {NUM} MiB",
|
||||
"TITLE": "诊断",
|
||||
"ENABLE_REBAR": "请在 BIOS 设置中启用 Resizable BAR 以获得最佳 VR 性能"
|
||||
},
|
||||
"TUTORIAL": "教程",
|
||||
"RESTART_WAYVR": "重启 WayVR",
|
||||
"CLOSE_WAYVR": "关闭 WayVR",
|
||||
"SPEECH_TO_TEXT": "语音转文本",
|
||||
"WHISPER_GPU_SELECT": "选择 GPU"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "应用启动器",
|
||||
"APPLICATION_STARTED": "应用程序已启动",
|
||||
@@ -264,7 +282,8 @@
|
||||
"SETTINGS": "音频设置",
|
||||
"SPEAKERS": "扬声器",
|
||||
"SPEAKERS_SET_SUCCESSFULLY": "扬声器设置成功",
|
||||
"VOLUME": "音量"
|
||||
"VOLUME": "音量",
|
||||
"SWITCH_TO_THIS_DEVICE": "切换至此设备"
|
||||
},
|
||||
"CLOSE_WINDOW": "关闭窗口",
|
||||
"CREATION_DATE": "创建日期",
|
||||
@@ -349,5 +368,17 @@
|
||||
"ADD_TO_FAVOURITES": "添加到固定应用",
|
||||
"ADD_TO_FAVOURITES_HINT": "保存预设并将其固定到应用抽屉",
|
||||
"REMOVE_FROM_FAVOURITES": "从固定应用中移除",
|
||||
"EMPTY": "暂无"
|
||||
"EMPTY": "暂无",
|
||||
"INSTALLED": "已安装",
|
||||
"NOT_INSTALLED": "未安装",
|
||||
"POWER_OPTIONS": {
|
||||
"TITLE": "电源选项",
|
||||
"SHUTDOWN": "关机",
|
||||
"SUSPEND": "暂停",
|
||||
"SHUTDOWN_ARE_YOU_SURE": "确定要关机吗?",
|
||||
"NOT_SUPPORTED": "电源选项需要 systemd 或 elogind。",
|
||||
"SUSPEND_ARE_YOU_SURE": "确定要让计算机进入睡眠状态吗?"
|
||||
},
|
||||
"YES": "确定",
|
||||
"NO": "否"
|
||||
}
|
||||
+134
-15
@@ -1,11 +1,11 @@
|
||||
use std::{path::PathBuf, rc::Rc};
|
||||
use std::{path::PathBuf, process::Command, rc::Rc};
|
||||
|
||||
use chrono::Timelike;
|
||||
use glam::Vec2;
|
||||
use strum::EnumCount;
|
||||
use wgui::{
|
||||
assets::{AssetPath, AssetProvider},
|
||||
components::button::ComponentButton,
|
||||
assets::{AssetPathRef, AssetProvider},
|
||||
components::{ComponentTrait, button::ComponentButton},
|
||||
event::{CallbackDataCommon, StyleSetRequest},
|
||||
font_config::WguiFontConfig,
|
||||
globals::WguiGlobals,
|
||||
@@ -17,12 +17,15 @@ use wgui::{
|
||||
task::Tasks,
|
||||
theme::WguiTheme,
|
||||
widget::{label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite},
|
||||
windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
|
||||
windowing::{
|
||||
context_menu::{self, ContextMenu},
|
||||
window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
|
||||
},
|
||||
};
|
||||
use wlx_common::{
|
||||
async_executor::AsyncExecutor,
|
||||
audio,
|
||||
dash_interface::{BoxDashInterface, ConfigChangeKind, DashPlayspaceTask},
|
||||
dash_interface::{BoxDashInterface, ConfigChangeKind, DashBackendTask, DashPlayspaceTask},
|
||||
locale::WayVRLangProvider,
|
||||
palette::load_palette,
|
||||
timestep::{self, Timestep},
|
||||
@@ -35,10 +38,11 @@ use crate::{
|
||||
settings::TabSettings, welcome::TabWelcome,
|
||||
},
|
||||
util::{
|
||||
popup_manager::{MountPopupOnceParams, PopupManager, PopupManagerParams},
|
||||
is_exec_installed,
|
||||
popup_manager::{MountPopupOnceParams, PopupHolder, PopupManager, PopupManagerParams},
|
||||
toast_manager::ToastManager,
|
||||
},
|
||||
views,
|
||||
views::{self, ViewUpdateParams},
|
||||
};
|
||||
|
||||
pub struct FrontendWidgets {
|
||||
@@ -74,9 +78,11 @@ pub struct Frontend<T> {
|
||||
toast_manager: ToastManager,
|
||||
timestep: Timestep,
|
||||
sounds_to_play: Vec<SoundType>,
|
||||
context_menu_power: ContextMenu,
|
||||
|
||||
window_audio_settings: WguiWindow,
|
||||
view_audio_settings: Option<views::audio_settings::View>,
|
||||
popup_dialog_box: PopupHolder<views::dialog_box::View>,
|
||||
}
|
||||
|
||||
pub struct FrontendUpdateParams<'a, T> {
|
||||
@@ -116,13 +122,16 @@ pub enum FrontendTask {
|
||||
MountPopupOnce(MountPopupOnceParams),
|
||||
RefreshPopupManager,
|
||||
ShowAudioSettings,
|
||||
ShowPowerSettings(WidgetID /* source widget */),
|
||||
UpdateAudioSettingsView,
|
||||
RecenterPlayspace,
|
||||
PushToast(Translation),
|
||||
PlaySound(SoundType),
|
||||
OpenURL(Rc<str>),
|
||||
RunCommand(String /* program */, Vec<String> /* args */),
|
||||
HideDashboard,
|
||||
MarkTutorialGraduated,
|
||||
BackendTask(DashBackendTask),
|
||||
}
|
||||
|
||||
impl<T: 'static> Frontend<T> {
|
||||
@@ -151,7 +160,7 @@ impl<T: 'static> Frontend<T> {
|
||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/dashboard.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/dashboard.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
LayoutParams {
|
||||
@@ -202,9 +211,11 @@ impl<T: 'static> Frontend<T> {
|
||||
popup_manager,
|
||||
toast_manager,
|
||||
window_audio_settings: WguiWindow::default(),
|
||||
context_menu_power: Default::default(),
|
||||
view_audio_settings: None,
|
||||
executor: params.executor,
|
||||
sounds_to_play: Vec::new(),
|
||||
popup_dialog_box: Default::default(),
|
||||
};
|
||||
|
||||
// init some things first
|
||||
@@ -220,7 +231,7 @@ impl<T: 'static> Frontend<T> {
|
||||
self.sounds_to_play.push(sound_type);
|
||||
}
|
||||
|
||||
fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> {
|
||||
fn play_sound(&mut self, audio: &mut Box<dyn audio::AudioProvider>, sound_type: SoundType) -> anyhow::Result<()> {
|
||||
let mut assets = self.globals.assets_builtin();
|
||||
|
||||
let path = match sound_type {
|
||||
@@ -236,7 +247,7 @@ impl<T: 'static> Frontend<T> {
|
||||
};
|
||||
|
||||
let sample = audio::AudioSample::from_mp3(&sound_bytes)?;
|
||||
audio_system.play_sample(&sample);
|
||||
audio.play_raw_sample(&sample);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -264,24 +275,79 @@ impl<T: 'static> Frontend<T> {
|
||||
pub fn process_update(
|
||||
&mut self,
|
||||
res: FrontendUpdateResult,
|
||||
audio_system: &mut audio::AudioSystem,
|
||||
audio_sample_player: &mut audio::SamplePlayer,
|
||||
audio: &mut Box<dyn audio::AudioProvider>,
|
||||
) -> anyhow::Result<()> {
|
||||
for sound_type in res.sounds_to_play {
|
||||
self.play_sound(audio_system, sound_type)?;
|
||||
self.play_sound(audio, sound_type)?;
|
||||
}
|
||||
|
||||
audio_sample_player.play_wgui_samples(audio_system, res.layout_result.sounds_to_play);
|
||||
audio.play_wgui_samples(res.layout_result.sounds_to_play);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn power_action_confirm(&mut self, power_action: PowerAction) {
|
||||
let translation_key = match power_action {
|
||||
PowerAction::Suspend => "POWER_OPTIONS.SUSPEND_ARE_YOU_SURE",
|
||||
PowerAction::Poweroff => "POWER_OPTIONS.SHUTDOWN_ARE_YOU_SURE",
|
||||
};
|
||||
|
||||
let tasks = self.tasks.clone();
|
||||
views::dialog_box::mount_popup(
|
||||
self.popup_dialog_box.clone(),
|
||||
self.tasks.clone(),
|
||||
views::dialog_box::Params {
|
||||
globals: self.globals.clone(),
|
||||
message: Translation::from_translation_key(translation_key),
|
||||
entries: views::dialog_box::get_entries_yes_no(),
|
||||
on_action_click: Box::new(move |action| {
|
||||
if action == "yes" {
|
||||
tasks.push(task_for_power_action(power_action));
|
||||
}
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn process_power_action(&mut self, action: &str, data: &mut T) {
|
||||
match action {
|
||||
"restart" => {
|
||||
self.interface.restart(data);
|
||||
}
|
||||
"close" => {
|
||||
self.interface.close(data);
|
||||
}
|
||||
"suspend" => {
|
||||
self.power_action_confirm(PowerAction::Suspend);
|
||||
}
|
||||
"shutdown" => {
|
||||
self.power_action_confirm(PowerAction::Poweroff);
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self, params: FrontendUpdateParams<T>) -> anyhow::Result<FrontendUpdateResult> {
|
||||
// fixme: timer events instead of this thing
|
||||
if self.ticks.is_multiple_of(1000) {
|
||||
self.update_time(params.data)?;
|
||||
}
|
||||
|
||||
// TODO: refactor: simplify update function (no configs or T are required in most cases)
|
||||
let mut config_change_kind = None;
|
||||
self.popup_dialog_box.update(&mut ViewUpdateParams {
|
||||
layout: &mut self.layout,
|
||||
executor: &self.executor,
|
||||
general_config: self.interface.general_config(params.data),
|
||||
config_change_kind: &mut config_change_kind,
|
||||
})?;
|
||||
|
||||
if let context_menu::TickResult::Action(action) = self.context_menu_power.tick(&mut self.layout, &mut self.state)? {
|
||||
self.process_power_action(&action, params.data);
|
||||
}
|
||||
|
||||
{
|
||||
// always 30 times per second
|
||||
while self.timestep.on_tick() {
|
||||
@@ -372,13 +438,16 @@ impl<T: 'static> Frontend<T> {
|
||||
FrontendTask::MountPopupOnce(popup_params) => self.mount_popup_once(popup_params, params.data)?,
|
||||
FrontendTask::RefreshPopupManager => self.refresh_popup_manager()?,
|
||||
FrontendTask::ShowAudioSettings => self.action_show_audio_settings()?,
|
||||
FrontendTask::ShowPowerSettings(pos) => self.action_show_power_settings(pos)?,
|
||||
FrontendTask::UpdateAudioSettingsView => self.action_update_audio_settings()?,
|
||||
FrontendTask::RecenterPlayspace => self.action_recenter_playspace(params.data)?,
|
||||
FrontendTask::PushToast(content) => self.toast_manager.push(content),
|
||||
FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type),
|
||||
FrontendTask::HideDashboard => self.action_hide_dashboard(params.data),
|
||||
FrontendTask::OpenURL(url) => self.action_open_url(url),
|
||||
FrontendTask::RunCommand(program, args) => self.action_run_command(program, args),
|
||||
FrontendTask::MarkTutorialGraduated => self.action_tutorial_graduated(params.data),
|
||||
FrontendTask::BackendTask(task) => self.interface.backend_task(params.data, task)?,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
@@ -401,7 +470,10 @@ impl<T: 'static> Frontend<T> {
|
||||
.cast_as::<WidgetSprite>(self.widgets.id_sprite_titlebar_icon)?;
|
||||
sprite.set_content(
|
||||
common.alterables,
|
||||
Some(CustomGlyphData::from_assets(&self.globals, AssetPath::BuiltIn(icon))?),
|
||||
Some(CustomGlyphData::from_assets(
|
||||
&self.globals,
|
||||
AssetPathRef::BuiltIn(icon),
|
||||
)?),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -501,6 +573,11 @@ impl<T: 'static> Frontend<T> {
|
||||
FrontendTask::ShowAudioSettings,
|
||||
);
|
||||
|
||||
let btn_power = self.state.fetch_component_as::<ComponentButton>("btn_power")?;
|
||||
self
|
||||
.tasks
|
||||
.handle_button(&btn_power, FrontendTask::ShowPowerSettings(btn_power.base().get_id()));
|
||||
|
||||
// "Recenter playspace" bottom bar button
|
||||
self.tasks.handle_button(
|
||||
&self.state.fetch_component_as::<ComponentButton>("btn_recenter")?,
|
||||
@@ -510,6 +587,18 @@ impl<T: 'static> Frontend<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_show_power_settings(&mut self, source_id: WidgetID) -> anyhow::Result<()> {
|
||||
self.context_menu_power.open(context_menu::OpenParams {
|
||||
on_custom_attribs: None,
|
||||
position: source_id.into(),
|
||||
blueprint: context_menu::Blueprint::Template {
|
||||
template_name: "context_menu_power_options".into(),
|
||||
template_params: Default::default(),
|
||||
},
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_show_audio_settings(&mut self) -> anyhow::Result<()> {
|
||||
self.window_audio_settings.open(&mut WguiWindowParams {
|
||||
position: Vec2::new(64.0, 64.0),
|
||||
@@ -574,4 +663,34 @@ impl<T: 'static> Frontend<T> {
|
||||
url
|
||||
))));
|
||||
}
|
||||
|
||||
fn action_run_command(&mut self, command: String, args: Vec<String>) {
|
||||
if let Err(e) = Command::new(command).args(args).spawn() {
|
||||
self
|
||||
.tasks
|
||||
.push(FrontendTask::PushToast(Translation::from_raw_text_string(format!(
|
||||
"Failed to launch command: {e}"
|
||||
))))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PowerAction {
|
||||
Suspend,
|
||||
Poweroff,
|
||||
}
|
||||
|
||||
pub fn task_for_power_action(action: PowerAction) -> FrontendTask {
|
||||
for cmd in ["systemctl", "loginctl"] {
|
||||
if is_exec_installed(cmd) {
|
||||
let (command, args) = match action {
|
||||
PowerAction::Suspend => (cmd.to_string(), vec!["suspend".to_string()]),
|
||||
PowerAction::Poweroff => (cmd.to_string(), vec!["poweroff".to_string()]),
|
||||
};
|
||||
log::debug!("Command line for {action:?}: {command} {}", args.join(" "));
|
||||
return FrontendTask::RunCommand(command, args);
|
||||
}
|
||||
}
|
||||
FrontendTask::PushToast(Translation::from_translation_key("POWER_OPTIONS.NOT_SUPPORTED"))
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{cell::RefCell, collections::VecDeque, marker::PhantomData, rc::Rc};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::{ButtonClickCallback, ComponentButton},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
@@ -61,7 +61,7 @@ impl<T> Tab<T> for TabApps<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_entry_from_app_name<'a>(app_id: &str, entries: &'a [DesktopEntry]) -> Option<&'a DesktopEntry> {
|
||||
fn find_entry_from_app_name<'a>(app_id: &str, entries: &'a [Rc<DesktopEntry>]) -> Option<&'a Rc<DesktopEntry>> {
|
||||
entries.iter().find(|&entry| *entry.app_id == *app_id)
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ impl<T> TabApps<T> {
|
||||
|
||||
let mut stale_entries = Vec::<Rc<str>>::new();
|
||||
|
||||
let mut pinned_desktop_entries = Vec::<(PinnedApp, &DesktopEntry)>::new();
|
||||
let mut pinned_desktop_entries = Vec::<(PinnedApp, Rc<DesktopEntry>)>::new();
|
||||
|
||||
// collect pinned desktop entries
|
||||
{
|
||||
@@ -83,7 +83,7 @@ impl<T> TabApps<T> {
|
||||
continue;
|
||||
};
|
||||
|
||||
pinned_desktop_entries.push((pinned_app.clone(), desktop_entry));
|
||||
pinned_desktop_entries.push((pinned_app.clone(), desktop_entry.clone()));
|
||||
}
|
||||
// cleanup:
|
||||
// remove non-existent app ids from pinned apps
|
||||
@@ -119,7 +119,7 @@ impl<T> TabApps<T> {
|
||||
&mut state.parser_state,
|
||||
&doc_params(frontend.globals.clone()),
|
||||
self.pinned_apps_parent,
|
||||
desktop_entry,
|
||||
desktop_entry.as_ref(),
|
||||
Some(tooltip_string),
|
||||
)?;
|
||||
|
||||
@@ -139,8 +139,8 @@ impl<T> TabApps<T> {
|
||||
|
||||
struct AppList {
|
||||
//data: Vec<ParserData>,
|
||||
all_entries: Vec<DesktopEntry>,
|
||||
entries_to_mount: VecDeque<DesktopEntry>,
|
||||
all_entries: Vec<Rc<DesktopEntry>>,
|
||||
entries_to_mount: VecDeque<Rc<DesktopEntry>>,
|
||||
list_parent: WidgetPair,
|
||||
prev_category_name: String,
|
||||
}
|
||||
@@ -150,7 +150,7 @@ fn on_app_click(
|
||||
frontend_tasks: FrontendTasks,
|
||||
tasks: Tasks<Task>,
|
||||
globals: WguiGlobals,
|
||||
entry: DesktopEntry,
|
||||
entry: Rc<DesktopEntry>,
|
||||
state: Rc<RefCell<State>>,
|
||||
pinned_app: Option<PinnedApp>,
|
||||
) -> ButtonClickCallback {
|
||||
@@ -170,7 +170,7 @@ fn on_app_click(
|
||||
fn doc_params(globals: WguiGlobals) -> ParseDocumentParams<'static> {
|
||||
ParseDocumentParams {
|
||||
globals,
|
||||
path: AssetPath::BuiltIn("gui/tab/apps.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/apps.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -307,14 +307,17 @@ fn get_category_name_score(name: &str) -> u8 {
|
||||
Scores::Unknown as u8
|
||||
}
|
||||
|
||||
fn get_best_category_name(categories: &[Rc<str>]) -> Option<&Rc<str>> {
|
||||
fn get_best_category_name<S>(categories: &[S]) -> Option<&str>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let mut best_score: u8 = 0;
|
||||
let mut best_category: Option<&Rc<str>> = None;
|
||||
let mut best_category: Option<&str> = None;
|
||||
|
||||
for cat in categories {
|
||||
let score = get_category_name_score(cat);
|
||||
let score = get_category_name_score(cat.as_ref());
|
||||
if score > best_score {
|
||||
best_category = Some(cat);
|
||||
best_category = Some(cat.as_ref());
|
||||
best_score = score;
|
||||
}
|
||||
}
|
||||
@@ -359,7 +362,7 @@ fn mount_entry<T>(
|
||||
params.insert(
|
||||
"src",
|
||||
if entry.icon_path.is_none() {
|
||||
"dashboard/terminal.svg"
|
||||
"@/dashboard/terminal.svg"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{marker::PhantomData, rc::Rc};
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
layout::{Layout, WidgetID},
|
||||
@@ -53,7 +53,7 @@ impl<T> Tab<T> for TabDonate<T> {
|
||||
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/donate.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/donate.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
layout::WidgetID,
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
};
|
||||
@@ -53,7 +53,7 @@ impl<T> TabGames<T> {
|
||||
let state = wgui::parser::parse_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/games.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/games.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
&mut frontend.layout,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::{marker::PhantomData, rc::Rc};
|
||||
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPath,
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
color::{WguiColor, WguiColorName, WguiNamedColor},
|
||||
components::{ComponentTrait, button::ComponentButton},
|
||||
event::CallbackDataCommon,
|
||||
@@ -61,7 +61,7 @@ fn get_supporter_anim(
|
||||
Animation::new_ex(
|
||||
btn.base().get_id(),
|
||||
1234,
|
||||
480,
|
||||
AnimationDuration::SecondsFixed(8.0),
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let opacity_in = f32::clamp(data.pos * FADE_SPEED, 0.0, 1.0);
|
||||
@@ -142,7 +142,7 @@ impl<T> TabHome<T> {
|
||||
let state = wgui::parser::parse_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals: frontend.layout.state.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/home.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/home.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
&mut frontend.layout,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{collections::HashMap, marker::PhantomData, rc::Rc};
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::{
|
||||
bar_graph::{ComponentBarGraph, ValueCell},
|
||||
button::ComponentButton,
|
||||
@@ -229,7 +229,7 @@ impl<T> Tab<T> for TabMonado<T> {
|
||||
fn doc_params_monado(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/monado.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/monado.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ fn doc_params_monado(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
fn doc_params_tab_process_list(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/monado_tab_process_list.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/monado_tab_process_list.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ fn doc_params_tab_process_list(globals: &'_ WguiGlobals) -> ParseDocumentParams<
|
||||
fn doc_params_tab_general_settings(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/monado_tab_general_settings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/monado_tab_general_settings.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -253,7 +253,7 @@ fn doc_params_tab_general_settings(globals: &'_ WguiGlobals) -> ParseDocumentPar
|
||||
fn doc_params_tab_debug_timings(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/monado_tab_debug_timings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/monado_tab_debug_timings.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::tab::settings::{self, SettingType, Task, horiz_cell, mount_requires_restart};
|
||||
use crate::{
|
||||
tab::settings::{self, SettingType, Task, horiz_cell, mount_requires_restart},
|
||||
util::wgui_simple,
|
||||
};
|
||||
use wgui::{
|
||||
components::{
|
||||
button::{ButtonClickEvent, ComponentButton},
|
||||
checkbox::ComponentCheckbox,
|
||||
slider::ComponentSlider,
|
||||
},
|
||||
components::{button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider},
|
||||
layout::{Layout, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||
task::Tasks,
|
||||
widget::label::WidgetLabel,
|
||||
windowing::context_menu,
|
||||
};
|
||||
use wlx_common::{DesktopBackend, XrBackend, config::GeneralConfig, dash_interface::InterfaceFeats};
|
||||
@@ -49,6 +47,49 @@ pub fn options_stat_row(mp: &mut MacroParams, parent: WidgetID, translation: &st
|
||||
mp.parser_state.get_widget_id(&id)
|
||||
}
|
||||
|
||||
pub fn options_diagnostics_row(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
title: &str,
|
||||
tooltip_str: &str,
|
||||
checked: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("title", title);
|
||||
params.insert("tooltip_str", tooltip_str);
|
||||
params.insert("color", if checked { "success" } else { "danger" });
|
||||
|
||||
params.insert(
|
||||
"sprite",
|
||||
if checked {
|
||||
"@/dashboard/check.svg"
|
||||
} else {
|
||||
"@/dashboard/cross.svg"
|
||||
},
|
||||
);
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "DiagnosticsRow", mp.layout, parent, params)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn options_diagnostics_drm_card(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
name: &str,
|
||||
info: &str,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("name", name);
|
||||
params.insert("info", info);
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "DiagnosticsDrmCard", mp.layout, parent, params)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn options_checkbox(mp: &mut MacroParams, parent: WidgetID, setting: SettingType) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
@@ -254,7 +295,6 @@ where
|
||||
mp.idx += 1;
|
||||
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("id", &id);
|
||||
|
||||
match setting.get_translation() {
|
||||
Ok(translation) => params.insert("translation", translation),
|
||||
@@ -267,69 +307,63 @@ where
|
||||
|
||||
let id_cell = horiz_cell(mp.layout, parent)?;
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, id_cell, params)?;
|
||||
let setting_str = setting.as_ref();
|
||||
let title = setting.get_enum_title(mp.config);
|
||||
|
||||
let feats = mp.feats;
|
||||
let cells = EnumType::VARIANTS
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
if item.get_bool("Hidden").unwrap_or(false) {
|
||||
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 title = SettingType::get_enum_title_inner(*item);
|
||||
let tooltip = SettingType::get_enum_tooltip_inner(*item);
|
||||
|
||||
let text = &title.text;
|
||||
let translated = if title.translated { "1" } else { "0" };
|
||||
let action = format!("{setting_str};{id};{value};{text};{translated}");
|
||||
|
||||
Some(context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(action.into()),
|
||||
title,
|
||||
tooltip,
|
||||
..Default::default()
|
||||
}))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let tasks = mp.tasks.clone();
|
||||
wgui_simple::mount_dropdown(wgui_simple::MountDropdownParams {
|
||||
layout: mp.layout,
|
||||
parser_state: mp.parser_state,
|
||||
doc_params: mp.doc_params,
|
||||
parent: id_cell,
|
||||
id,
|
||||
params,
|
||||
current_text: title,
|
||||
cells,
|
||||
on_open: Box::new(move |pos, cells| tasks.push(Task::OpenContextMenu(pos, cells))),
|
||||
})?;
|
||||
|
||||
if setting.requires_restart() {
|
||||
mount_requires_restart(mp.layout, id_cell)?;
|
||||
}
|
||||
|
||||
let setting_str = setting.as_ref();
|
||||
let title = setting.get_enum_title(mp.config);
|
||||
|
||||
{
|
||||
let mut label = mp
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&mp.layout.state, &format!("{id}_value"))?;
|
||||
label.set_text_simple(&mut mp.layout.state.globals.get(), title);
|
||||
}
|
||||
|
||||
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||
btn.on_click(Rc::new({
|
||||
let feats = mp.feats;
|
||||
let tasks = mp.tasks.clone();
|
||||
move |_common, e: ButtonClickEvent| {
|
||||
tasks.push(Task::OpenContextMenu(
|
||||
e.mouse_pos_absolute.unwrap_or_default(),
|
||||
EnumType::VARIANTS
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
if item.get_bool("Hidden").unwrap_or(false) {
|
||||
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 title = SettingType::get_enum_title_inner(*item);
|
||||
let tooltip = SettingType::get_enum_tooltip_inner(*item);
|
||||
|
||||
let text = &title.text;
|
||||
let translated = if title.translated { "1" } else { "0" };
|
||||
|
||||
Some(context_menu::Cell {
|
||||
action_name: Some(format!("{setting_str};{id};{value};{text};{translated}").into()),
|
||||
title,
|
||||
tooltip,
|
||||
attribs: vec![],
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use glam::Vec2;
|
||||
use std::{marker::PhantomData, rc::Rc, str::FromStr};
|
||||
use strum::{AsRefStr, EnumProperty, EnumString};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
color::WguiColorName,
|
||||
components::tabs::ComponentTabs,
|
||||
event::StyleSetRequest,
|
||||
@@ -35,6 +34,7 @@ use crate::{
|
||||
mod macros;
|
||||
mod tab_autostart_apps;
|
||||
mod tab_controls;
|
||||
mod tab_diagnostics;
|
||||
mod tab_features;
|
||||
mod tab_look_and_feel;
|
||||
mod tab_misc;
|
||||
@@ -53,6 +53,7 @@ pub(crate) enum TabNameEnum {
|
||||
Skybox,
|
||||
SpaceDrag,
|
||||
Statistics,
|
||||
Diagnostics,
|
||||
Troubleshooting,
|
||||
}
|
||||
|
||||
@@ -67,6 +68,7 @@ impl TabNameEnum {
|
||||
"skybox" => Some(TabNameEnum::Skybox),
|
||||
"space_drag" => Some(TabNameEnum::SpaceDrag),
|
||||
"statistics" => Some(TabNameEnum::Statistics),
|
||||
"diagnostics" => Some(TabNameEnum::Diagnostics),
|
||||
"troubleshooting" => Some(TabNameEnum::Troubleshooting),
|
||||
_ => None,
|
||||
}
|
||||
@@ -78,11 +80,10 @@ pub(crate) enum Task {
|
||||
ClearPipewireTokens,
|
||||
ClearSavedState,
|
||||
DeleteAllConfigs,
|
||||
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
||||
OpenContextMenu(context_menu::Position, Vec<context_menu::Cell>),
|
||||
RemoveAutostartApp(Rc<str>),
|
||||
ResetPlayspace,
|
||||
ResetPlayspaceCenter,
|
||||
RestartSoftware,
|
||||
SavePlayspaceCenter,
|
||||
SetTab(TabNameEnum),
|
||||
SettingUpdated(SettingType),
|
||||
@@ -140,6 +141,7 @@ pub struct TabSettings<T> {
|
||||
tasks: Tasks<Task>,
|
||||
marker: PhantomData<T>,
|
||||
frontend_tasks: FrontendTasks,
|
||||
feats: InterfaceFeats,
|
||||
}
|
||||
|
||||
impl<T> Tab<T> for TabSettings<T> {
|
||||
@@ -228,10 +230,6 @@ impl<T> Tab<T> for TabSettings<T> {
|
||||
frontend.interface.playspace_task(data, DashPlayspaceTask::Reset)?;
|
||||
return Ok(());
|
||||
}
|
||||
Task::RestartSoftware => {
|
||||
frontend.interface.restart(data);
|
||||
return Ok(());
|
||||
}
|
||||
Task::OpenContextMenu(position, cells) => {
|
||||
self.context_menu.open(context_menu::OpenParams {
|
||||
on_custom_attribs: None,
|
||||
@@ -347,6 +345,7 @@ pub(crate) enum SettingType {
|
||||
NotificationsEnabled,
|
||||
NotificationsSoundEnabled,
|
||||
OpaqueBackground,
|
||||
MiddleGrabsSingle,
|
||||
MouseAcceleration,
|
||||
PointerLerpFactor,
|
||||
MouseSpeed,
|
||||
@@ -403,6 +402,7 @@ impl SettingType {
|
||||
Self::NotificationsEnabled => &mut config.notifications_enabled,
|
||||
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
|
||||
Self::OpaqueBackground => &mut config.opaque_background,
|
||||
Self::MiddleGrabsSingle => &mut config.middle_grabs_single,
|
||||
Self::MouseAcceleration => &mut config.wvr_mouse_acceleration,
|
||||
Self::ScreenRenderDown => &mut config.screen_render_down,
|
||||
Self::SetsOnWatch => &mut config.sets_on_watch,
|
||||
@@ -553,6 +553,7 @@ impl SettingType {
|
||||
Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"),
|
||||
Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"),
|
||||
Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"),
|
||||
Self::MiddleGrabsSingle => Ok("APP_SETTINGS.MIDDLE_GRABS_SINGLE"),
|
||||
Self::MouseSpeed => Ok("APP_SETTINGS.POINTER_SPEED"),
|
||||
Self::MouseAcceleration => Ok("APP_SETTINGS.POINTER_ACCELERATION"),
|
||||
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
|
||||
@@ -602,6 +603,7 @@ impl SettingType {
|
||||
Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"),
|
||||
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
|
||||
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
|
||||
Self::MiddleGrabsSingle => Some("APP_SETTINGS.MIDDLE_GRABS_SINGLE_HELP"),
|
||||
Self::MouseAcceleration => Some("APP_SETTINGS.POINTER_ACCELERATION_HELP"),
|
||||
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
|
||||
Self::SnapAngleDeg => Some("APP_SETTINGS.SNAP_ANGLE_DEG_HELP"),
|
||||
@@ -687,7 +689,7 @@ fn mount_requires_restart(layout: &mut Layout, parent: WidgetID) -> anyhow::Resu
|
||||
fn doc_params(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/settings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/settings.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -696,10 +698,14 @@ impl<T> TabSettings<T> {
|
||||
fn set_tab(&mut self, frontend: &mut Frontend<T>, data: &mut T, name: TabNameEnum) -> anyhow::Result<()> {
|
||||
let root = self.state.get_widget_id("settings_root")?;
|
||||
frontend.layout.remove_children(root);
|
||||
let globals = frontend.layout.state.globals.clone();
|
||||
self.current_tab = None;
|
||||
let globals = frontend.layout.state.globals.clone();
|
||||
|
||||
let feats = frontend.interface.get_feats(data);
|
||||
let vulkan_devices = if matches!(name, TabNameEnum::Features) {
|
||||
Some(frontend.interface.enumerate_vulkan_devices(data)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut mp = MacroParams {
|
||||
layout: &mut frontend.layout,
|
||||
@@ -708,14 +714,14 @@ impl<T> TabSettings<T> {
|
||||
config: frontend.interface.general_config(data),
|
||||
tasks: self.tasks.clone(),
|
||||
idx: 9001,
|
||||
feats,
|
||||
feats: self.feats,
|
||||
};
|
||||
|
||||
let settings_mount_params = SettingsMountParams {
|
||||
mp: &mut mp,
|
||||
id_parent: root,
|
||||
frontend_tasks: &self.frontend_tasks,
|
||||
feats,
|
||||
feats: self.feats,
|
||||
};
|
||||
|
||||
match name {
|
||||
@@ -723,7 +729,10 @@ impl<T> TabSettings<T> {
|
||||
self.current_tab = Some(Box::new(tab_look_and_feel::State::mount(settings_mount_params)?));
|
||||
}
|
||||
TabNameEnum::Features => {
|
||||
self.current_tab = Some(Box::new(tab_features::State::mount(settings_mount_params)?));
|
||||
self.current_tab = Some(Box::new(tab_features::State::mount(
|
||||
settings_mount_params,
|
||||
vulkan_devices.unwrap(), /* safe */
|
||||
)?));
|
||||
}
|
||||
TabNameEnum::SpaceDrag => {
|
||||
self.current_tab = Some(Box::new(tab_space_drag::State::mount(settings_mount_params)?));
|
||||
@@ -749,6 +758,9 @@ impl<T> TabSettings<T> {
|
||||
TabNameEnum::Statistics => {
|
||||
self.current_tab = Some(Box::new(tab_statistics::State::mount(settings_mount_params)?));
|
||||
}
|
||||
TabNameEnum::Diagnostics => {
|
||||
self.current_tab = Some(Box::new(tab_diagnostics::State::mount(settings_mount_params)?));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -757,7 +769,7 @@ impl<T> TabSettings<T> {
|
||||
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, data: &mut T) -> anyhow::Result<Self> {
|
||||
let doc_params = ParseDocumentParams {
|
||||
globals: frontend.layout.state.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/settings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/settings.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
@@ -786,6 +798,8 @@ impl<T> TabSettings<T> {
|
||||
|
||||
tasks.push(Task::SetTab(TabNameEnum::LookAndFeel));
|
||||
|
||||
let feats = frontend.interface.get_feats(data);
|
||||
|
||||
Ok(Self {
|
||||
app_button_ids: Vec::new(),
|
||||
tasks,
|
||||
@@ -794,6 +808,7 @@ impl<T> TabSettings<T> {
|
||||
context_menu: ContextMenu::default(),
|
||||
current_tab: None,
|
||||
frontend_tasks: frontend.tasks.clone(),
|
||||
feats,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ impl State {
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"APP_SETTINGS.AUTOSTART_APPS",
|
||||
"dashboard/apps.svg",
|
||||
"@/dashboard/apps.svg",
|
||||
)?;
|
||||
|
||||
// todo: prevent clone
|
||||
|
||||
@@ -3,7 +3,10 @@ use wgui::parser::TemplateParams;
|
||||
use wgui::{
|
||||
components::button::ComponentButton, globals::WguiGlobals, layout::WidgetID, parser::Fetchable, task::Tasks,
|
||||
};
|
||||
use wlx_common::XrBackend;
|
||||
use wlx_common::dash_interface::DashBackendTask;
|
||||
|
||||
use crate::frontend::FrontendTask;
|
||||
use crate::tab::settings::{UpdateExtra, horiz_cell, mount_requires_restart};
|
||||
use crate::util::popup_manager::PopupHolder;
|
||||
|
||||
@@ -18,7 +21,8 @@ use crate::{
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Task {
|
||||
OpenInputProfiles,
|
||||
OpenInputProfilesDash,
|
||||
OpenInputProfilesBackend,
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
@@ -34,13 +38,23 @@ impl SettingsTab for State {
|
||||
|
||||
for task in self.tasks.drain() {
|
||||
match task {
|
||||
Task::OpenInputProfiles => {
|
||||
Task::OpenInputProfilesDash => {
|
||||
input_profiles::mount_popup(
|
||||
self.frontend_tasks.clone(),
|
||||
self.globals.clone(),
|
||||
self.popup_input_profiles.clone(),
|
||||
);
|
||||
}
|
||||
Task::OpenInputProfilesBackend => {
|
||||
self
|
||||
.frontend_tasks
|
||||
.push(FrontendTask::BackendTask(DashBackendTask::ShowBindingsUI));
|
||||
|
||||
// overlay sort order doesn't work on steamvr,
|
||||
// so the dashboard would be drawn over the bindings UI
|
||||
// while the bindings UI has input focus
|
||||
self.frontend_tasks.push(FrontendTask::HideDashboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +67,7 @@ fn create_input_profiles_button(
|
||||
parent: WidgetID,
|
||||
tasks: Tasks<Task>,
|
||||
_popup: &PopupHolder<input_profiles::View>,
|
||||
xr_backend: XrBackend,
|
||||
) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
@@ -62,7 +77,7 @@ fn create_input_profiles_button(
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("id", &id);
|
||||
params.insert("translation", "APP_SETTINGS.INPUT_PROFILES");
|
||||
params.insert("icon", "dashboard/controller.svg");
|
||||
params.insert("icon", "@/dashboard/controller.svg");
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, id_cell, params)?;
|
||||
@@ -71,7 +86,11 @@ fn create_input_profiles_button(
|
||||
btn.on_click(Rc::new({
|
||||
let tasks = tasks.clone();
|
||||
move |_common, _e| {
|
||||
tasks.push(Task::OpenInputProfiles);
|
||||
if xr_backend.is_open_vr() {
|
||||
tasks.push(Task::OpenInputProfilesBackend);
|
||||
} else {
|
||||
tasks.push(Task::OpenInputProfilesDash);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
@@ -90,16 +109,15 @@ impl State {
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"APP_SETTINGS.CONTROLS",
|
||||
"dashboard/controller.svg",
|
||||
"@/dashboard/controller.svg",
|
||||
)?;
|
||||
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, par.feats.xr_backend)?;
|
||||
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::HandsfreeAltTab>(par.mp, c, &SettingType::HandsfreeAltTab)?;
|
||||
options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?;
|
||||
options_checkbox(par.mp, c, SettingType::LeftHandedMouse)?;
|
||||
options_checkbox(par.mp, c, SettingType::MiddleGrabsSingle)?;
|
||||
options_checkbox(par.mp, c, SettingType::AllowSliding)?;
|
||||
options_checkbox(par.mp, c, SettingType::InvertScrollDirectionX)?;
|
||||
options_checkbox(par.mp, c, SettingType::InvertScrollDirectionY)?;
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
use wgui::layout::WidgetID;
|
||||
|
||||
use crate::{
|
||||
tab::settings::{
|
||||
SettingsMountParams, SettingsTab,
|
||||
macros::{MacroParams, options_category, options_diagnostics_drm_card, options_diagnostics_row},
|
||||
},
|
||||
util::is_exec_installed,
|
||||
};
|
||||
|
||||
pub struct State {}
|
||||
|
||||
impl SettingsTab for State {}
|
||||
|
||||
#[derive(Default)]
|
||||
struct LspciInfo {
|
||||
// slot: String,
|
||||
// class: String,
|
||||
vendor: String,
|
||||
device: String,
|
||||
// s_vendor: String,
|
||||
}
|
||||
|
||||
fn lspci_info(vendor: &str /* hex */, device: &str /* hex */) -> Option<LspciInfo> {
|
||||
// example output for "lspci -vmmd 1002:747e":
|
||||
//
|
||||
// Slot: 0b:00.0
|
||||
// Class: VGA compatible controller
|
||||
// Vendor: Advanced Micro Devices, Inc. [AMD/ATI]
|
||||
// Device: Navi 32 [Radeon RX 7700 XT / 7800 XT]
|
||||
// SVendor: Sapphire Technology Limited
|
||||
// SDevice: Device 475a
|
||||
// Rev: c8
|
||||
// ProgIf: 00
|
||||
|
||||
let mut cmd = std::process::Command::new("lspci");
|
||||
cmd.arg("-vmmd");
|
||||
cmd.arg(format!("{}:{}", vendor, device));
|
||||
|
||||
let res = cmd.output().ok()?;
|
||||
|
||||
if !res.status.success() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut info = LspciInfo::default();
|
||||
|
||||
let stdout = str::from_utf8(&res.stdout).ok()?;
|
||||
for line in stdout.lines() {
|
||||
let Some((key, value)) = line.split_once(":") else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if key == "Device" {
|
||||
info.device = String::from(value.trim());
|
||||
}
|
||||
}
|
||||
|
||||
Some(info)
|
||||
}
|
||||
|
||||
fn mount_installed_path(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
exec: &str,
|
||||
reason_translation: Option<&str>,
|
||||
) -> anyhow::Result<()> {
|
||||
let title = if is_exec_installed(exec) {
|
||||
"INSTALLED"
|
||||
} else {
|
||||
"NOT_INSTALLED"
|
||||
};
|
||||
|
||||
let title_translated = mp.layout.state.globals.i18n().translate(title);
|
||||
let tooltip = if let Some(reason) = reason_translation {
|
||||
format!(
|
||||
"{}\n{}",
|
||||
title_translated,
|
||||
mp.layout.state.globals.i18n().translate(reason)
|
||||
)
|
||||
} else {
|
||||
title_translated.to_string()
|
||||
};
|
||||
options_diagnostics_row(mp, parent, exec, &tooltip, is_exec_installed(exec))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_sysfs_param(device_path: &str, param: &str) -> anyhow::Result<String> {
|
||||
let string = std::fs::read_to_string(format!("{}/{}", device_path, param))?;
|
||||
Ok(string.trim().into())
|
||||
}
|
||||
|
||||
fn read_sysfs_param_int(device_path: &str, param: &str) -> anyhow::Result<u64> {
|
||||
Ok(read_sysfs_param(device_path, param)?.parse::<u64>()?)
|
||||
}
|
||||
|
||||
fn mount_drm_card(mp: &mut MacroParams, parent: WidgetID, device_path: &str) -> anyhow::Result<()> {
|
||||
let vendor = read_sysfs_param(device_path, "vendor")?;
|
||||
let device = read_sysfs_param(device_path, "device")?;
|
||||
let vram_total = read_sysfs_param_int(device_path, "mem_info_vram_total").ok();
|
||||
let vis_vram_total = read_sysfs_param_int(device_path, "mem_info_vis_vram_total").ok();
|
||||
|
||||
let name = match lspci_info(&vendor, &device) {
|
||||
Some(info) => {
|
||||
format!("{} {}", info.vendor, info.device)
|
||||
}
|
||||
None => format!("{}:{}", vendor, device),
|
||||
};
|
||||
|
||||
let info = if let Some(vram_total) = vram_total
|
||||
&& let Some(vis_vram_total) = vis_vram_total
|
||||
{
|
||||
let mut s = mp.layout.state.globals.i18n().translate_and_replace(
|
||||
"APP_SETTINGS.DIAGNOSTICS.CPU_ACCESSIBLE_VRAM",
|
||||
(
|
||||
"{NUM}",
|
||||
&format!("{}/{}", vis_vram_total / 1024 / 1024, vram_total / 1024 / 1024),
|
||||
),
|
||||
);
|
||||
|
||||
if vis_vram_total != vram_total {
|
||||
s += " [ALERT!]\nEnable Resizable BAR in the BIOS settings for optimal VR performance";
|
||||
}
|
||||
|
||||
s
|
||||
} else {
|
||||
String::from("No info")
|
||||
};
|
||||
|
||||
options_diagnostics_drm_card(mp, parent, &name, &info)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mount_drm_cards(mp: &mut MacroParams, parent: WidgetID) -> anyhow::Result<()> {
|
||||
for file in std::fs::read_dir("/sys/class/drm/")?.flatten() {
|
||||
let file_name = file.file_name();
|
||||
let Some(file_name) = file_name.to_str() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !file_name.starts_with("renderD") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Err(e) = mount_drm_card(mp, parent, &format!("/sys/class/drm/{}/device", file_name)) {
|
||||
log::error!("failed to mount drm card: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<Self> {
|
||||
let c = options_category(
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"APP_SETTINGS.DIAGNOSTICS.TITLE",
|
||||
"@/dashboard/diagnostics.svg",
|
||||
)?;
|
||||
|
||||
mount_installed_path(par.mp, c, "pactl", Some("APP_SETTINGS.DIAGNOSTICS_REASON.PACTL"))?;
|
||||
mount_installed_path(par.mp, c, "cage", Some("APP_SETTINGS.DIAGNOSTICS_REASON.CAGE"))?;
|
||||
mount_installed_path(
|
||||
par.mp,
|
||||
c,
|
||||
"xwayland-satellite",
|
||||
Some("APP_SETTINGS.DIAGNOSTICS_REASON.XWAYLAND_SATELLITE"),
|
||||
)?;
|
||||
mount_installed_path(par.mp, c, "xdg-open", Some("APP_SETTINGS.DIAGNOSTICS_REASON.XDG_OPEN"))?;
|
||||
mount_installed_path(par.mp, c, "steam", None)?;
|
||||
|
||||
mount_drm_cards(par.mp, c)?;
|
||||
|
||||
Ok(State {})
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use wgui::{
|
||||
components::button::{ButtonClickEvent, ComponentButton},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::WidgetID,
|
||||
@@ -9,7 +8,7 @@ use wgui::{
|
||||
parser::{Fetchable, TemplateParams},
|
||||
task::Tasks,
|
||||
widget::label::WidgetLabel,
|
||||
windowing::context_menu::{self},
|
||||
windowing::context_menu,
|
||||
};
|
||||
use wlx_common::{async_executor::AsyncExecutor, config::GeneralConfig, dash_interface::ConfigChangeKind};
|
||||
|
||||
@@ -21,6 +20,7 @@ use crate::{
|
||||
},
|
||||
util::{
|
||||
popup_manager::PopupHolder,
|
||||
wgui_simple,
|
||||
whisper::{
|
||||
WHISPER_MODELS, WhisperModel, whisper_any_models_downloaded, whisper_delete_all_models, whisper_model_from_name,
|
||||
whisper_model_path,
|
||||
@@ -104,49 +104,75 @@ impl SettingsTab for State {
|
||||
layout: &mut wgui::layout::Layout,
|
||||
state: &mut wgui::parser::ParserState,
|
||||
) -> anyhow::Result<()> {
|
||||
if let (Some(_), Some(id), Some(model_name)) = {
|
||||
let mut s = action.splitn(3, ';');
|
||||
(s.next(), s.next(), s.next())
|
||||
} {
|
||||
if !model_name.is_empty()
|
||||
&& let Some(model) = whisper_model_from_name(model_name)
|
||||
{
|
||||
let mut common = layout.common();
|
||||
let mut label = state.fetch_widget_as::<WidgetLabel>(common.state, &format!("{id}_value"))?;
|
||||
label.set_text(&mut common, Translation::from_raw_text(model.display_name));
|
||||
let (Some(_), Some(_type), Some(id), Some(value)) = ({
|
||||
let mut s = action.splitn(4, ';');
|
||||
(s.next(), s.next(), s.next(), s.next())
|
||||
}) else {
|
||||
debug_assert!(false);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
config.whisper_model = model.file_name.into();
|
||||
if !whisper_model_path(model.file_name).exists() {
|
||||
self.show_whisper_model_dialog_box_download(model)?;
|
||||
match _type {
|
||||
"whisper_model" => {
|
||||
let model_name = value;
|
||||
if !model_name.is_empty()
|
||||
&& let Some(model) = whisper_model_from_name(model_name)
|
||||
{
|
||||
let mut common = layout.common();
|
||||
let mut label = state.fetch_widget_as::<WidgetLabel>(common.state, &format!("{id}_value"))?;
|
||||
label.set_text(&mut common, Translation::from_raw_text(model.display_name));
|
||||
|
||||
config.whisper_model = model.file_name.into();
|
||||
if !whisper_model_path(model.file_name).exists() {
|
||||
self.show_whisper_model_dialog_box_download(model)?;
|
||||
} else {
|
||||
change_kind.replace(ConfigChangeKind::Other);
|
||||
}
|
||||
} else {
|
||||
config.whisper_model = "".into();
|
||||
change_kind.replace(ConfigChangeKind::Other);
|
||||
}
|
||||
} else {
|
||||
config.whisper_model = "".into();
|
||||
change_kind.replace(ConfigChangeKind::Other);
|
||||
// re-init the whole tab
|
||||
if whisper_any_models_downloaded().unwrap_or_default() {
|
||||
self.show_whisper_model_dialog_box_cleanup()?;
|
||||
} else {
|
||||
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
|
||||
// re-init the whole tab
|
||||
if whisper_any_models_downloaded().unwrap_or_default() {
|
||||
self.show_whisper_model_dialog_box_cleanup()?;
|
||||
} else {
|
||||
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"whisper_gpu" => {
|
||||
let mut common = layout.common();
|
||||
let mut label = state.fetch_widget_as::<WidgetLabel>(common.state, &format!("{id}_value"))?;
|
||||
config.whisper_gpu = value.parse::<u32>().unwrap();
|
||||
label.set_text(
|
||||
&mut common,
|
||||
Translation::from_raw_text_string(config.whisper_gpu.to_string()),
|
||||
);
|
||||
change_kind.replace(ConfigChangeKind::Other);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
||||
pub fn mount(par: SettingsMountParams, vulkan_devices: Vec<String>) -> anyhow::Result<State> {
|
||||
let tasks = Tasks::<Task>::new();
|
||||
let popup_download = PopupHolder::<views::download_file::View>::default();
|
||||
let popup_dialog = PopupHolder::<views::dialog_box::View>::default();
|
||||
|
||||
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.FEATURES", "dashboard/options.svg")?;
|
||||
let c = options_category(
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"APP_SETTINGS.FEATURES",
|
||||
"@/dashboard/options.svg",
|
||||
)?;
|
||||
|
||||
if par.feats.whisper {
|
||||
let c = options_category(par.mp, c, "APP_SETTINGS.SPEECH_TO_TEXT", "@/dashboard/stt.svg")?;
|
||||
whisper_models_dropdown(par.mp, c)?;
|
||||
whisper_gpu_select_dropdown(par.mp, c, vulkan_devices)?;
|
||||
}
|
||||
|
||||
options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?;
|
||||
@@ -213,12 +239,12 @@ impl State {
|
||||
entries: vec![
|
||||
views::dialog_box::ButtonEntry {
|
||||
content: Translation::from_translation_key("APP_SETTINGS.CANCEL"),
|
||||
icon: "dashboard/close.svg",
|
||||
icon: "@/dashboard/close.svg",
|
||||
action: ACTION_CANCEL,
|
||||
},
|
||||
views::dialog_box::ButtonEntry {
|
||||
content: Translation::from_translation_key("DOWNLOAD"),
|
||||
icon: "dashboard/download.svg",
|
||||
icon: "@/dashboard/download.svg",
|
||||
action: ACTION_DOWNLOAD,
|
||||
},
|
||||
],
|
||||
@@ -254,12 +280,12 @@ impl State {
|
||||
entries: vec![
|
||||
views::dialog_box::ButtonEntry {
|
||||
content: Translation::from_translation_key("APP_SETTINGS.CANCEL"),
|
||||
icon: "dashboard/close.svg",
|
||||
icon: "@/dashboard/close.svg",
|
||||
action: ACTION_CANCEL,
|
||||
},
|
||||
views::dialog_box::ButtonEntry {
|
||||
content: Translation::from_translation_key("REMOVE"),
|
||||
icon: "dashboard/trash.svg",
|
||||
icon: "@/dashboard/trash.svg",
|
||||
action: ACTION_REMOVE,
|
||||
},
|
||||
],
|
||||
@@ -282,6 +308,48 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
fn whisper_gpu_select_dropdown(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
vulkan_devices: Vec<String>,
|
||||
) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
|
||||
let parent = horiz_cell(mp.layout, parent)?;
|
||||
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("translation", "APP_SETTINGS.WHISPER_GPU_SELECT");
|
||||
|
||||
let current_text = Translation::from_raw_text_string(mp.config.whisper_gpu.to_string());
|
||||
|
||||
let cells = vulkan_devices
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, name)| !name.contains("llvmpipe"))
|
||||
.map(|(idx, name)| {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(format!(";whisper_gpu;{};{}", id, idx).into()),
|
||||
title: Translation::from_raw_text_string(name.to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let tasks = mp.tasks.clone();
|
||||
wgui_simple::mount_dropdown(wgui_simple::MountDropdownParams {
|
||||
layout: mp.layout,
|
||||
parser_state: mp.parser_state,
|
||||
doc_params: mp.doc_params,
|
||||
parent,
|
||||
id,
|
||||
params,
|
||||
current_text,
|
||||
cells,
|
||||
on_open: Box::new(move |pos, cells| tasks.push(ParentTask::OpenContextMenu(pos, cells))),
|
||||
})
|
||||
}
|
||||
|
||||
fn whisper_models_dropdown(mp: &mut MacroParams, parent: WidgetID) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
@@ -302,56 +370,49 @@ fn whisper_models_dropdown(mp: &mut MacroParams, parent: WidgetID) -> anyhow::Re
|
||||
});
|
||||
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("id", &id);
|
||||
params.insert("translation", "APP_SETTINGS.WHISPER_MODEL");
|
||||
params.insert("tooltip", "APP_SETTINGS.WHISPER_MODEL_HELP");
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
|
||||
|
||||
{
|
||||
let mut label = mp
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&mp.layout.state, &format!("{id}_value"))?;
|
||||
label.set_text_simple(&mut mp.layout.state.globals.get(), current_translation);
|
||||
}
|
||||
|
||||
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||
btn.on_click(Rc::new({
|
||||
let parent_tasks = mp.tasks.clone();
|
||||
move |_common, e: ButtonClickEvent| {
|
||||
let mut cells = WHISPER_MODELS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, item)| context_menu::Cell {
|
||||
action_name: Some(format!(";{id};{}", item.file_name).into()),
|
||||
title: Translation::from_raw_text_string(format!(
|
||||
"{}{}",
|
||||
item.display_name,
|
||||
if downloaded_models.contains(&idx) { " ✅" } else { "" }
|
||||
)),
|
||||
tooltip: None,
|
||||
attribs: vec![],
|
||||
let mut cells = WHISPER_MODELS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, item)| {
|
||||
if downloaded_models.contains(&idx) {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(format!(";whisper_model;{id};{}", item.file_name).into()),
|
||||
title: Translation::from_raw_text(item.display_name),
|
||||
sprite_src_builtin: Some("@/dashboard/check.svg".into()),
|
||||
..Default::default()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
} else {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(format!(";whisper_model;{id};{}", item.file_name).into()),
|
||||
title: Translation::from_raw_text(item.display_name),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
cells.insert(
|
||||
0,
|
||||
context_menu::Cell {
|
||||
action_name: Some(format!(";{id};").into()),
|
||||
title: Translation::from_translation_key("APP_SETTINGS.OPTION.NONE"),
|
||||
tooltip: None,
|
||||
attribs: vec![],
|
||||
},
|
||||
);
|
||||
cells.insert(
|
||||
0,
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(format!(";whisper_model;{id};").into()),
|
||||
title: Translation::from_translation_key("APP_SETTINGS.OPTION.NONE"),
|
||||
..Default::default()
|
||||
}),
|
||||
);
|
||||
|
||||
parent_tasks.push(ParentTask::OpenContextMenu(
|
||||
e.mouse_pos_absolute.unwrap_or_default(),
|
||||
cells,
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
let tasks = mp.tasks.clone();
|
||||
wgui_simple::mount_dropdown(wgui_simple::MountDropdownParams {
|
||||
layout: mp.layout,
|
||||
parser_state: mp.parser_state,
|
||||
doc_params: mp.doc_params,
|
||||
parent,
|
||||
id,
|
||||
params,
|
||||
current_text: current_translation,
|
||||
cells,
|
||||
on_open: Box::new(move |pos, cells| tasks.push(ParentTask::OpenContextMenu(pos, cells))),
|
||||
})
|
||||
}
|
||||
@@ -60,7 +60,7 @@ impl State {
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"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)?;
|
||||
@@ -100,7 +100,7 @@ fn create_color_palettes_button(
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("id", &id);
|
||||
params.insert("translation", "APP_SETTINGS.COLOR_PALETTE");
|
||||
params.insert("icon", "dashboard/palette.svg");
|
||||
params.insert("icon", "@/dashboard/palette.svg");
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, id_cell, params)?;
|
||||
|
||||
@@ -9,7 +9,7 @@ impl SettingsTab for State {}
|
||||
|
||||
impl 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::InputCaptureMethod>(par.mp, c, &SettingType::InputCaptureMethod)?;
|
||||
options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use wgui::{assets::AssetPath, i18n::Translation, layout::Layout, task::Tasks};
|
||||
use wgui::{assets::AssetPathRef, i18n::Translation, layout::Layout, task::Tasks};
|
||||
|
||||
use crate::{
|
||||
frontend::FrontendTasks,
|
||||
@@ -37,7 +37,7 @@ impl SettingsTab for State {
|
||||
|
||||
impl State {
|
||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<Self> {
|
||||
let id_category = options_category(par.mp, par.id_parent, "APP_SETTINGS.SKYBOX", "dashboard/globe.svg")?;
|
||||
let id_category = options_category(par.mp, par.id_parent, "APP_SETTINGS.SKYBOX", "@/dashboard/globe.svg")?;
|
||||
options_checkbox(par.mp, id_category, SettingType::UseSkybox)?;
|
||||
options_checkbox(par.mp, id_category, SettingType::UsePassthrough)?;
|
||||
options_slider_f32(par.mp, id_category, SettingType::GridOpacity, 0.0, 1.0, 0.05)?;
|
||||
@@ -49,7 +49,7 @@ impl State {
|
||||
id_parent: id_category,
|
||||
layout: par.mp.layout,
|
||||
content: Translation::from_translation_key("APP_SETTINGS.BROWSE_SKYMAPS"),
|
||||
icon_builtin: AssetPath::BuiltIn("dashboard/globe.svg"),
|
||||
icon_builtin: AssetPathRef::BuiltIn("dashboard/globe.svg"),
|
||||
on_click: tasks.get_button_click_callback(Task::ShowSkymapList),
|
||||
})?;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutTask, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams},
|
||||
@@ -36,14 +36,14 @@ impl SettingsTab for State {
|
||||
|
||||
impl State {
|
||||
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
|
||||
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.SPACE_DRAG", "dashboard/drag.svg")?;
|
||||
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.SPACE_DRAG", "@/dashboard/drag.svg")?;
|
||||
|
||||
let globals = par.mp.layout.state.globals.clone();
|
||||
|
||||
let tab_state = wgui::parser::parse_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals,
|
||||
path: AssetPath::BuiltIn("gui/tab/settings_tab_space_drag.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/settings_tab_space_drag.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
par.mp.layout,
|
||||
@@ -61,7 +61,7 @@ impl State {
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.RESET_PLAYSPACE",
|
||||
"dashboard/refresh.svg",
|
||||
"@/dashboard/refresh.svg",
|
||||
super::Task::ResetPlayspace,
|
||||
)?;
|
||||
|
||||
@@ -69,7 +69,7 @@ impl State {
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.SAVE_PLAYSPACE_CENTER",
|
||||
"dashboard/recenter.svg",
|
||||
"@/dashboard/recenter.svg",
|
||||
super::Task::SavePlayspaceCenter,
|
||||
)?;
|
||||
|
||||
@@ -77,7 +77,7 @@ impl State {
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.RESET_PLAYSPACE_CENTER",
|
||||
"dashboard/trash.svg",
|
||||
"@/dashboard/trash.svg",
|
||||
super::Task::ResetPlayspaceCenter,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ impl State {
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"APP_SETTINGS.STATISTICS",
|
||||
"dashboard/barchart.svg",
|
||||
"@/dashboard/barchart.svg",
|
||||
)?;
|
||||
|
||||
let id_label_rotations = options_stat_row(par.mp, c, "APP_SETTINGS.ROTATIONS")?;
|
||||
|
||||
@@ -13,36 +13,29 @@ impl State {
|
||||
par.mp,
|
||||
par.id_parent,
|
||||
"APP_SETTINGS.TROUBLESHOOTING",
|
||||
"dashboard/cpu.svg",
|
||||
"@/dashboard/cpu.svg",
|
||||
)?;
|
||||
options_danger_button(
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS",
|
||||
"dashboard/display.svg",
|
||||
"@/dashboard/display.svg",
|
||||
Task::ClearPipewireTokens,
|
||||
)?;
|
||||
options_danger_button(
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.CLEAR_SAVED_STATE",
|
||||
"dashboard/binary.svg",
|
||||
"@/dashboard/binary.svg",
|
||||
Task::ClearSavedState,
|
||||
)?;
|
||||
options_danger_button(
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.DELETE_ALL_CONFIGS",
|
||||
"dashboard/circle.svg",
|
||||
"@/dashboard/circle.svg",
|
||||
Task::DeleteAllConfigs,
|
||||
)?;
|
||||
options_danger_button(
|
||||
par.mp,
|
||||
c,
|
||||
"APP_SETTINGS.RESTART_SOFTWARE",
|
||||
"dashboard/refresh.svg",
|
||||
Task::RestartSoftware,
|
||||
)?;
|
||||
Ok(State {})
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{marker::PhantomData, rc::Rc};
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
layout::{Layout, WidgetID},
|
||||
@@ -68,7 +68,7 @@ impl<T> Tab<T> for TabWelcome<T> {
|
||||
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/welcome.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/tab/welcome.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ impl<T> TabWelcome<T> {
|
||||
let state = wgui::parser::parse_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals,
|
||||
path: AssetPath::BuiltIn(&format!("gui/tab/welcome_page_{}.xml", self.current_page)),
|
||||
path: AssetPathRef::BuiltIn(&format!("gui/tab/welcome_page_{}.xml", self.current_page)),
|
||||
extra: Default::default(),
|
||||
},
|
||||
layout,
|
||||
|
||||
@@ -7,3 +7,16 @@ pub mod steam_utils;
|
||||
pub mod toast_manager;
|
||||
pub mod wgui_simple;
|
||||
pub mod whisper;
|
||||
|
||||
// works good enough
|
||||
pub fn is_exec_installed(exec: &str) -> bool {
|
||||
let mut cmd = std::process::Command::new("sh");
|
||||
cmd.arg("-c");
|
||||
cmd.arg(format!("command -v {}", exec));
|
||||
|
||||
let Ok(res) = cmd.output() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
res.status.success()
|
||||
}
|
||||
@@ -81,7 +81,7 @@ impl BindingsDropdown for XrInputComponent {
|
||||
pub struct ParsedOpenXrInputPath {
|
||||
pub side: XrInputSide,
|
||||
pub subpath: XrInputSubpathKind,
|
||||
pub component: XrInputComponent,
|
||||
pub component: Option<XrInputComponent>,
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for ParsedOpenXrInputPath {
|
||||
@@ -101,13 +101,18 @@ impl TryFrom<&str> for ParsedOpenXrInputPath {
|
||||
bail!("missing input prefix");
|
||||
}
|
||||
|
||||
let (identifier, component) = rest.rsplit_once('/').context("missing identifier or component")?;
|
||||
let (identifier, component) = match rest.rsplit_once('/') {
|
||||
Some((ident, comp)) if !comp.is_empty() => {
|
||||
let comp = XrInputComponent::try_from(comp).context("bad component")?;
|
||||
(ident, Some(comp))
|
||||
}
|
||||
_ => (rest, None),
|
||||
};
|
||||
|
||||
if identifier.is_empty() || component.is_empty() {
|
||||
bail!("identifier or component empty");
|
||||
if identifier.is_empty() {
|
||||
bail!("identifier empty");
|
||||
}
|
||||
|
||||
let component = XrInputComponent::try_from(component).context("bad component")?;
|
||||
let subpath = XrInputSubpathKind::try_from(identifier).context("bad subpath")?;
|
||||
|
||||
Ok(Self {
|
||||
|
||||
@@ -21,6 +21,9 @@ pub struct Volume {
|
||||
|
||||
#[serde(rename = "front-right")]
|
||||
pub front_right: Option<VolumeChannel>,
|
||||
|
||||
#[serde(rename = "mono")]
|
||||
pub mono: Option<VolumeChannel>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
@@ -207,7 +210,7 @@ pub fn list_sources() -> anyhow::Result<Vec<Source>> {
|
||||
// exclude all monitor sources
|
||||
sources.retain(|source| match &source.properties.device_class {
|
||||
Some(c) => c != "monitor",
|
||||
None => false,
|
||||
None => true, /* unknown, pass it */
|
||||
});
|
||||
|
||||
Ok(sources)
|
||||
@@ -242,6 +245,8 @@ pub fn get_source_volume(source: &Source) -> anyhow::Result<f32> {
|
||||
front_left
|
||||
} else if let Some(aux0) = &source.volume.aux0 {
|
||||
aux0
|
||||
} else if let Some(mono) = &source.volume.mono {
|
||||
mono
|
||||
} else {
|
||||
return Ok(0.0); // fail silently
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ use std::{
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
use glam::Vec2;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
event::{EventAlterables, StyleSetRequest},
|
||||
globals::WguiGlobals,
|
||||
@@ -12,7 +14,7 @@ use wgui::{
|
||||
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
taffy::Rect,
|
||||
widget::label::WidgetLabel,
|
||||
widget::{WidgetObj, label::WidgetLabel},
|
||||
};
|
||||
use wlx_common::config::GeneralConfig;
|
||||
|
||||
@@ -251,6 +253,13 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
struct MountPopupPrepareResult {
|
||||
popup_handle: PopupHandle,
|
||||
id_content: WidgetID,
|
||||
id_top_bar_contents: WidgetID,
|
||||
id_popup_title: WidgetID,
|
||||
}
|
||||
|
||||
impl PopupManager {
|
||||
pub fn new(params: PopupManagerParams) -> Self {
|
||||
Self {
|
||||
@@ -273,16 +282,17 @@ impl PopupManager {
|
||||
frontend_tasks: &FrontendTasks,
|
||||
popup_title: &Translation,
|
||||
popup_padding: PopupPadding,
|
||||
) -> anyhow::Result<(PopupHandle, WidgetID /* content widget ID */)> {
|
||||
) -> anyhow::Result<MountPopupPrepareResult> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/popup_window.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/popup_window.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
let state = wgui::parser::parse_from_assets(doc_params, layout, self.parent_id)?;
|
||||
|
||||
let id_root = state.get_widget_id("root")?;
|
||||
let id_content = state.get_widget_id("content")?;
|
||||
let id_top_bar_contents = state.get_widget_id("top_bar_contents")?;
|
||||
|
||||
let padding = match popup_padding {
|
||||
PopupPadding::Normal => 16.0_f32,
|
||||
@@ -294,10 +304,11 @@ impl PopupManager {
|
||||
StyleSetRequest::Padding(Rect::length(padding)),
|
||||
));
|
||||
|
||||
{
|
||||
let id_popup_title = {
|
||||
let mut label_title = state.fetch_widget_as::<WidgetLabel>(&layout.state, "popup_title")?;
|
||||
label_title.set_text_simple(&mut globals.get(), popup_title.clone());
|
||||
}
|
||||
label_title.get_id()
|
||||
};
|
||||
|
||||
let but_back = state.fetch_component_as::<ComponentButton>("but_back")?;
|
||||
|
||||
@@ -338,7 +349,13 @@ impl PopupManager {
|
||||
});
|
||||
|
||||
frontend_tasks.push(FrontendTask::RefreshPopupManager);
|
||||
Ok((popup_handle, id_content))
|
||||
|
||||
Ok(MountPopupPrepareResult {
|
||||
popup_handle,
|
||||
id_content,
|
||||
id_top_bar_contents,
|
||||
id_popup_title,
|
||||
})
|
||||
}
|
||||
|
||||
/// Mount a new popup on top of the existing popup stack.
|
||||
@@ -356,18 +373,43 @@ impl PopupManager {
|
||||
anyhow::bail!("mount_popup_once called more than once");
|
||||
};
|
||||
|
||||
let (popup_handle, id_content) =
|
||||
self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title, params.extra.padding)?;
|
||||
let res = self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title, params.extra.padding)?;
|
||||
|
||||
// text fade-in
|
||||
Animation::effect_label_fade_in(
|
||||
res.id_popup_title,
|
||||
AnimationDuration::Seconds(0.25),
|
||||
AnimationEasing::OutQuad,
|
||||
)
|
||||
.submit_l(layout);
|
||||
|
||||
// top bar slide
|
||||
Animation::effect_slide(
|
||||
res.id_top_bar_contents,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(10.0, 0.0),
|
||||
)
|
||||
.submit_l(layout);
|
||||
|
||||
// content slide
|
||||
Animation::effect_slide(
|
||||
res.id_content,
|
||||
AnimationDuration::Seconds(0.5),
|
||||
AnimationEasing::OutQuint,
|
||||
Vec2::new(5.0, 0.0),
|
||||
)
|
||||
.submit_l(layout);
|
||||
|
||||
// mount user-set popup content
|
||||
let closed_callback = on_content_func(PopupContentFuncData {
|
||||
layout,
|
||||
handle: popup_handle.clone(),
|
||||
id_content,
|
||||
handle: res.popup_handle.clone(),
|
||||
id_content: res.id_content,
|
||||
config,
|
||||
})?;
|
||||
|
||||
popup_handle.state.borrow_mut().closed_callback = Some(closed_callback);
|
||||
res.popup_handle.state.borrow_mut().closed_callback = Some(closed_callback);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use glam::{Mat4, Vec3};
|
||||
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
|
||||
i18n::Translation,
|
||||
@@ -45,7 +45,9 @@ impl Drop for MountedToast {
|
||||
}
|
||||
}
|
||||
|
||||
const TOAST_DURATION_TICKS: u32 = 150;
|
||||
fn def_toast_duration() -> AnimationDuration {
|
||||
AnimationDuration::Seconds(2.5)
|
||||
}
|
||||
|
||||
impl ToastManager {
|
||||
pub fn new() -> Self {
|
||||
@@ -116,9 +118,9 @@ impl ToastManager {
|
||||
let (label, _) = layout.add_child(rect.id, label, taffy::Style { ..Default::default() })?;
|
||||
|
||||
// show-up animation
|
||||
layout.animations.add(Animation::new(
|
||||
Animation::new(
|
||||
rect.id,
|
||||
(TOAST_DURATION_TICKS as f32 * layout.state.theme.animation_mult) as u32,
|
||||
def_toast_duration(),
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0));
|
||||
@@ -143,7 +145,8 @@ impl ToastManager {
|
||||
);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
));
|
||||
)
|
||||
.submit_l(layout);
|
||||
|
||||
state.toast = Some(MountedToast {
|
||||
id_root: root.id,
|
||||
@@ -165,7 +168,7 @@ impl ToastManager {
|
||||
|
||||
if state.timeout == 0 {
|
||||
state.toast = None;
|
||||
state.timeout = TOAST_DURATION_TICKS;
|
||||
state.timeout = def_toast_duration().to_ticks(layout.state.ticks_per_second, layout.state.theme.animation_mult);
|
||||
// mount next
|
||||
if let Some(content) = state.queue.pop_front() {
|
||||
self.mount_toast(layout, &mut state, content)?;
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
use glam::{Mat4, Vec2};
|
||||
use std::rc::Rc;
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPath,
|
||||
animation::{Animation, AnimationDuration, AnimationEasing},
|
||||
assets::AssetPathRef,
|
||||
color::WguiColorName,
|
||||
components::{self, button::ButtonClickCallback},
|
||||
components::{
|
||||
self,
|
||||
button::{ButtonClickCallback, ButtonClickEvent, ComponentButton},
|
||||
},
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutTask, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||
renderer_vk::{
|
||||
text::{FontWeight, TextStyle, custom_glyph::CustomGlyphData},
|
||||
util::centered_matrix,
|
||||
@@ -17,13 +21,14 @@ use wgui::{
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
sprite::{WidgetSprite, WidgetSpriteParams},
|
||||
},
|
||||
windowing::context_menu,
|
||||
};
|
||||
|
||||
pub struct CreateButtonParams<'a> {
|
||||
pub id_parent: WidgetID,
|
||||
pub layout: &'a mut Layout,
|
||||
pub content: Translation,
|
||||
pub icon_builtin: AssetPath<'a>,
|
||||
pub icon_builtin: AssetPathRef<'a>,
|
||||
pub on_click: ButtonClickCallback,
|
||||
}
|
||||
|
||||
@@ -84,7 +89,12 @@ pub fn create_label_error(layout: &mut Layout, parent: WidgetID, content: String
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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: AssetPathRef,
|
||||
) -> anyhow::Result<WidgetID> {
|
||||
let widget_sprite = WidgetSprite::create(WidgetSpriteParams {
|
||||
color: Some(WguiColorName::OnBackground.into()),
|
||||
glyph_data: Some(CustomGlyphData::from_assets(&layout.state.globals, path)?),
|
||||
@@ -119,7 +129,7 @@ pub struct CreateLoadingParams<'a> {
|
||||
pub fn create_loading(par: CreateLoadingParams) -> anyhow::Result<WidgetID> {
|
||||
let doc_params = ParseDocumentParams {
|
||||
globals: par.layout.state.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/t_loading.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/t_loading.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
@@ -140,9 +150,9 @@ pub fn create_loading(par: CreateLoadingParams) -> anyhow::Result<WidgetID> {
|
||||
let id_root = data.get_widget_id("root")?;
|
||||
let id_sprite_loading = data.get_widget_id("sprite_loading")?;
|
||||
|
||||
par.layout.animations.add(Animation::new(
|
||||
Animation::new(
|
||||
id_sprite_loading,
|
||||
60 * 30, /* spin it for 30 seconds at most */
|
||||
AnimationDuration::SecondsFixed(120.0), /* spin it for 120 seconds at most */
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
// spin it
|
||||
@@ -156,7 +166,44 @@ pub fn create_loading(par: CreateLoadingParams) -> anyhow::Result<WidgetID> {
|
||||
}
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
));
|
||||
)
|
||||
.submit_l(par.layout);
|
||||
|
||||
Ok(id_root)
|
||||
}
|
||||
|
||||
pub struct MountDropdownParams<'a> {
|
||||
pub layout: &'a mut Layout,
|
||||
pub parser_state: &'a mut ParserState,
|
||||
pub doc_params: &'a ParseDocumentParams<'a>,
|
||||
pub parent: WidgetID,
|
||||
pub id: String,
|
||||
pub params: TemplateParams,
|
||||
pub current_text: Translation,
|
||||
pub cells: Vec<context_menu::Cell>,
|
||||
pub on_open: Box<dyn Fn(context_menu::Position, Vec<context_menu::Cell>)>,
|
||||
}
|
||||
|
||||
pub fn mount_dropdown(par: MountDropdownParams) -> anyhow::Result<()> {
|
||||
let mut params = par.params;
|
||||
params.insert("id", &par.id);
|
||||
|
||||
par
|
||||
.parser_state
|
||||
.instantiate_template(par.doc_params, "DropdownButton", par.layout, par.parent, params)?;
|
||||
|
||||
{
|
||||
let mut label = par
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&par.layout.state, &format!("{}_value", par.id))?;
|
||||
label.set_text_simple(&mut par.layout.state.globals.get(), par.current_text);
|
||||
}
|
||||
|
||||
let btn = par.parser_state.fetch_component_as::<ComponentButton>(&par.id)?;
|
||||
btn.on_click(Rc::new(move |_common, e: ButtonClickEvent| {
|
||||
(par.on_open)(e.mouse_pos_absolute.into(), par.cells.clone());
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc, str::FromStr};
|
||||
use strum::VariantNames;
|
||||
use wayvr_ipc::packet_client::{PositionMode, WvrProcessLaunchParams};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::{
|
||||
ComponentTrait, button::ComponentButton, checkbox::ComponentCheckbox, radio_group::ComponentRadioGroup,
|
||||
},
|
||||
@@ -53,7 +53,7 @@ struct LaunchParams<'a, T> {
|
||||
pub struct View {
|
||||
#[allow(dead_code)]
|
||||
state: ParserState,
|
||||
entry: DesktopEntry,
|
||||
entry: Rc<DesktopEntry>,
|
||||
tasks: Tasks<Task>,
|
||||
frontend_tasks: FrontendTasks,
|
||||
globals: WguiGlobals,
|
||||
@@ -80,7 +80,7 @@ pub struct View {
|
||||
|
||||
pub struct Params<'a> {
|
||||
pub globals: &'a WguiGlobals,
|
||||
pub entry: DesktopEntry,
|
||||
pub entry: Rc<DesktopEntry>,
|
||||
pub layout: &'a mut Layout,
|
||||
pub parent_id: WidgetID,
|
||||
pub config: &'a GeneralConfig,
|
||||
@@ -100,7 +100,7 @@ impl View {
|
||||
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/app_launcher.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/app_launcher.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
@@ -119,10 +119,8 @@ impl View {
|
||||
{
|
||||
let mut label_exec = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "label_exec")?;
|
||||
|
||||
label_exec.set_text_simple(
|
||||
&mut params.globals.get(),
|
||||
Translation::from_raw_text_string(format!("{} {}", params.entry.exec_path, params.entry.exec_args)),
|
||||
);
|
||||
let command = shell_words::join(params.entry.exec_argv.iter().map(|x| x.as_ref()));
|
||||
label_exec.set_text_simple(&mut params.globals.get(), Translation::from_raw_text_string(command));
|
||||
}
|
||||
|
||||
let tasks = Tasks::new();
|
||||
@@ -406,14 +404,19 @@ impl View {
|
||||
env.push("ELECTRON_OZONE_PLATFORM_HINT=wayland".into());
|
||||
}
|
||||
|
||||
let args = match params.compositor_mode {
|
||||
AppCompositorMode::Cage => format!("-- {} {}", params.application.exec_path, params.application.exec_args),
|
||||
AppCompositorMode::Native => params.application.exec_args.to_string(),
|
||||
};
|
||||
|
||||
let exec = match params.compositor_mode {
|
||||
AppCompositorMode::Cage => "cage".to_string(),
|
||||
AppCompositorMode::Native => params.application.exec_path.to_string(),
|
||||
let argv = match params.compositor_mode {
|
||||
AppCompositorMode::Cage => ["cage", "--"]
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(params.application.exec_argv.iter().map(|x| x.as_ref()))
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
AppCompositorMode::Native => params
|
||||
.application
|
||||
.exec_argv
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
};
|
||||
|
||||
let pos_mode = match params.pos_mode {
|
||||
@@ -423,7 +426,7 @@ impl View {
|
||||
};
|
||||
|
||||
let mut userdata = HashMap::new();
|
||||
userdata.insert("desktop-entry".to_string(), serde_json::to_string(params.application)?);
|
||||
userdata.insert("desktop-entry".into(), serde_json::to_string(params.application)?);
|
||||
|
||||
let resolution = Self::calculate_resolution(params.res_mode, params.orientation_mode);
|
||||
|
||||
@@ -432,12 +435,11 @@ impl View {
|
||||
params.auto_start,
|
||||
WvrProcessLaunchParams {
|
||||
env,
|
||||
exec,
|
||||
argv,
|
||||
name: params.application.app_name.to_string(),
|
||||
args,
|
||||
resolution,
|
||||
pos_mode,
|
||||
icon: params.application.icon_path.as_ref().map(|x| x.as_ref().to_string()),
|
||||
icon: params.application.icon_path.as_deref().map(String::from),
|
||||
userdata,
|
||||
},
|
||||
)?;
|
||||
@@ -486,7 +488,7 @@ impl View {
|
||||
pub fn mount_popup(
|
||||
frontend_tasks: FrontendTasks,
|
||||
globals: WguiGlobals,
|
||||
entry: DesktopEntry,
|
||||
entry: Rc<DesktopEntry>,
|
||||
popup: PopupHolder<View>,
|
||||
on_app_pins_changed: Box<dyn Fn()>,
|
||||
pinned_app: Option<PinnedApp>,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::{AssetPathRef, AssetPathSource},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{
|
||||
self,
|
||||
@@ -12,9 +12,9 @@ use wgui::{
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams, strip_path_as},
|
||||
task::Tasks,
|
||||
widget::ConstructEssentials,
|
||||
widget::{ConstructEssentials, rectangle::WidgetRectangle},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -100,7 +100,7 @@ struct ProfileDisplayName {
|
||||
struct SelectorCell {
|
||||
key: String,
|
||||
display_text: String,
|
||||
icon_path: &'static str,
|
||||
icon_path_builtin: &'static str,
|
||||
}
|
||||
|
||||
struct MultiSelectorParams<'a> {
|
||||
@@ -124,7 +124,7 @@ fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
|
||||
params.ess,
|
||||
components::button::Params {
|
||||
text: Some(Translation::from_raw_text(&cell.display_text)),
|
||||
sprite_src: Some(AssetPath::BuiltIn(cell.icon_path)),
|
||||
sprite_src: Some(strip_path_as(AssetPathSource::BuiltIn, cell.icon_path_builtin).unwrap()),
|
||||
color,
|
||||
..Default::default()
|
||||
},
|
||||
@@ -211,7 +211,7 @@ fn get_profile_display_name(profile_name: &str, card: &pactl_wrapper::Card) -> P
|
||||
// fallback
|
||||
return ProfileDisplayName {
|
||||
name: profile_name.into(),
|
||||
icon_path: "dashboard/binary.svg",
|
||||
icon_path: "@/dashboard/binary.svg",
|
||||
is_vr: false,
|
||||
};
|
||||
};
|
||||
@@ -221,26 +221,26 @@ fn get_profile_display_name(profile_name: &str, card: &pactl_wrapper::Card) -> P
|
||||
|
||||
let prof = profile_name.to_lowercase();
|
||||
if prof.contains("analog") {
|
||||
out_icon_path = "dashboard/minijack.svg";
|
||||
out_icon_path = "@/dashboard/minijack.svg";
|
||||
} else if prof.contains("iec" /* digital */) {
|
||||
out_icon_path = "dashboard/binary.svg";
|
||||
out_icon_path = "@/dashboard/binary.svg";
|
||||
} else if prof.contains("hdmi") {
|
||||
out_icon_path = "dashboard/displayport.svg";
|
||||
out_icon_path = "@/dashboard/displayport.svg";
|
||||
} else if prof.contains("off") {
|
||||
out_icon_path = "dashboard/sleep.svg";
|
||||
out_icon_path = "@/dashboard/sleep.svg";
|
||||
} else if prof.contains("input") {
|
||||
out_icon_path = "dashboard/microphone.svg";
|
||||
out_icon_path = "@/dashboard/microphone.svg";
|
||||
} else {
|
||||
out_icon_path = "dashboard/volume.svg"; // Default fallback
|
||||
out_icon_path = "@/dashboard/volume.svg"; // Default fallback
|
||||
}
|
||||
|
||||
// All ports are tied to this VR headset, assign all of them to the VR icon
|
||||
if is_card_mentioning_hmd(card) {
|
||||
if prof.contains("mic") {
|
||||
// Probably microphone
|
||||
out_icon_path = "dashboard/microphone.svg";
|
||||
out_icon_path = "@/dashboard/microphone.svg";
|
||||
} else {
|
||||
out_icon_path = "dashboard/vr.svg";
|
||||
out_icon_path = "@/dashboard/vr.svg";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,11 +266,11 @@ fn get_profile_display_name(profile_name: &str, card: &pactl_wrapper::Card) -> P
|
||||
|
||||
if does_string_mention_hmd_sink(product_name) {
|
||||
// VR icon
|
||||
out_icon_path = "dashboard/vr.svg";
|
||||
out_icon_path = "@/dashboard/vr.svg";
|
||||
is_vr = true;
|
||||
} else {
|
||||
// Monitor icon
|
||||
out_icon_path = "dashboard/displayport.svg";
|
||||
out_icon_path = "@/dashboard/displayport.svg";
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -291,7 +291,7 @@ fn get_profile_display_name(profile_name: &str, card: &pactl_wrapper::Card) -> P
|
||||
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/audio_settings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/audio_settings.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -402,7 +402,7 @@ struct MountDeviceSliderParams<'a> {
|
||||
checked: bool,
|
||||
muted: bool,
|
||||
disp: Option<ProfileDisplayName>,
|
||||
alt_desc: String,
|
||||
device_desc: String,
|
||||
}
|
||||
|
||||
fn push_popup_speakers_set_successfully(globals: &WguiGlobals, frontend_tasks: &FrontendTasks, name: &str) {
|
||||
@@ -775,22 +775,22 @@ impl View {
|
||||
par.insert("device_name", &disp.name);
|
||||
par.insert("device_icon", disp.icon_path);
|
||||
} else {
|
||||
let icon_path = if params.alt_desc.contains("WiVRn") {
|
||||
"dashboard/wivrn_head_symbolic.svg"
|
||||
let icon_path = if params.device_desc.contains("WiVRn") {
|
||||
"@/dashboard/wivrn_head_symbolic.svg"
|
||||
} else {
|
||||
"dashboard/binary.svg"
|
||||
"@/dashboard/binary.svg"
|
||||
};
|
||||
|
||||
par.insert("device_name", ¶ms.alt_desc);
|
||||
par.insert("device_name", ¶ms.device_desc);
|
||||
par.insert("device_icon", icon_path);
|
||||
}
|
||||
|
||||
par.insert(
|
||||
"volume_icon",
|
||||
if params.muted {
|
||||
"dashboard/volume_off.svg"
|
||||
"@/dashboard/volume_off.svg"
|
||||
} else {
|
||||
"dashboard/volume.svg"
|
||||
"@/dashboard/volume.svg"
|
||||
},
|
||||
);
|
||||
|
||||
@@ -802,6 +802,13 @@ impl View {
|
||||
par,
|
||||
)?;
|
||||
|
||||
if params.checked {
|
||||
let rect = data.fetch_widget(¶ms.layout.state, "rect")?;
|
||||
let mut rect = rect.widget.cast::<WidgetRectangle>()?;
|
||||
rect.set_color(&mut params.layout.common(), WguiColorName::BackgroundVariant.into());
|
||||
rect.set_border_color(&mut params.layout.common(), WguiColorName::Primary.into());
|
||||
}
|
||||
|
||||
let mut common = params.layout.common();
|
||||
let checkbox = data.fetch_component_as::<ComponentCheckbox>("checkbox")?;
|
||||
let btn_mute = data.fetch_component_as::<ComponentButton>("btn_mute")?;
|
||||
@@ -858,7 +865,7 @@ impl View {
|
||||
false
|
||||
};
|
||||
|
||||
let alt_desc = sink.description.clone();
|
||||
let device_desc = sink.description.clone();
|
||||
let muted = sink.mute;
|
||||
|
||||
let control = Rc::new(ControlSink::new(self.tasks.clone(), self.on_update.clone(), sink));
|
||||
@@ -870,7 +877,7 @@ impl View {
|
||||
self.mount_device_slider(MountDeviceSliderParams {
|
||||
checked,
|
||||
disp,
|
||||
alt_desc,
|
||||
device_desc,
|
||||
layout,
|
||||
control,
|
||||
muted,
|
||||
@@ -898,7 +905,7 @@ impl View {
|
||||
false
|
||||
};
|
||||
|
||||
let alt_desc = source.description.clone();
|
||||
let device_desc = source.description.clone();
|
||||
let muted = source.mute;
|
||||
|
||||
let control = Rc::new(ControlSource::new(self.tasks.clone(), self.on_update.clone(), source));
|
||||
@@ -910,7 +917,7 @@ impl View {
|
||||
self.mount_device_slider(MountDeviceSliderParams {
|
||||
checked,
|
||||
disp,
|
||||
alt_desc,
|
||||
device_desc,
|
||||
layout,
|
||||
control,
|
||||
muted,
|
||||
@@ -968,7 +975,7 @@ impl View {
|
||||
cells.push(SelectorCell {
|
||||
key: profile_name.clone(),
|
||||
display_text: disp_name.name,
|
||||
icon_path: disp_name.icon_path,
|
||||
icon_path_builtin: disp_name.icon_path,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+684
-111
@@ -2,23 +2,19 @@ use glam::Vec2;
|
||||
use std::rc::Rc;
|
||||
use strum::EnumProperty;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::{
|
||||
button::{ButtonClickEvent, ComponentButton},
|
||||
slider::ComponentSlider,
|
||||
},
|
||||
assets::AssetPathRef,
|
||||
components::{button::ComponentButton, slider::ComponentSlider},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
log::LogErr,
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
|
||||
task::Tasks,
|
||||
widget::label::WidgetLabel,
|
||||
windowing::context_menu::{self, TickResult},
|
||||
};
|
||||
use wlx_common::{
|
||||
config_io,
|
||||
openxr_actions::{OneOrMany, OpenXrInputAction, OpenXrInputProfile, load_xr_input_profiles},
|
||||
openxr_actions::{OneOrMany, OpenXrInputAction, OpenXrInputChordMember, OpenXrInputProfile, load_xr_input_profiles},
|
||||
openxr_bindings_schema::{
|
||||
DEFAULT_BUTTON_THRESHOLDS, XrControllerProfile, XrInputComponent, XrInputSide, XrInputSubpathKind,
|
||||
},
|
||||
@@ -39,8 +35,11 @@ use crate::{
|
||||
enum Task {
|
||||
Save,
|
||||
Cancel,
|
||||
OpenContextMenu(glam::Vec2, Vec<context_menu::Cell>),
|
||||
OpenContextMenu(context_menu::Position, Vec<context_menu::Cell>),
|
||||
UpdateThreshold(Rc<str>, XrInputSide, usize, f32),
|
||||
AddChordMember(Rc<str>, XrInputSide),
|
||||
RemoveChordMember(Rc<str>, XrInputSide, usize),
|
||||
UpdateChordThreshold(Rc<str>, XrInputSide, usize, usize, f32),
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
@@ -100,53 +99,114 @@ impl ViewTrait for View {
|
||||
};
|
||||
|
||||
threshold[i] = val;
|
||||
log::warn!("UpdateThreshold {action_name} {side:?} {threshold:?}");
|
||||
}
|
||||
Task::AddChordMember(action_name, output_side) => {
|
||||
if let Some(member) = default_chord_member(self.controller_profile, output_side) {
|
||||
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
||||
let action_mut = get_action_mut(cur_profile, &action_name);
|
||||
action_chord_mut(action_mut, output_side)
|
||||
.get_or_insert_default()
|
||||
.push(member);
|
||||
self.refresh(par.layout)?;
|
||||
}
|
||||
}
|
||||
Task::RemoveChordMember(action_name, output_side, member_idx) => {
|
||||
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
||||
let action_mut = get_action_mut(cur_profile, &action_name);
|
||||
let chord = action_chord_mut(action_mut, output_side);
|
||||
let chord_empty = if let Some(members) = chord.as_mut()
|
||||
&& member_idx < members.len()
|
||||
{
|
||||
members.remove(member_idx);
|
||||
members.is_empty()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if chord_empty {
|
||||
*chord = None;
|
||||
}
|
||||
self.refresh(par.layout)?;
|
||||
}
|
||||
Task::UpdateChordThreshold(action_name, output_side, member_idx, i, val) => {
|
||||
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
||||
let action_mut = get_action_mut(cur_profile, &action_name);
|
||||
if let Some(member) = action_chord_mut(action_mut, output_side)
|
||||
.as_mut()
|
||||
.and_then(|members| members.get_mut(member_idx))
|
||||
{
|
||||
let mut threshold = member.threshold().unwrap_or(DEFAULT_BUTTON_THRESHOLDS);
|
||||
threshold[i] = val;
|
||||
set_chord_member_threshold(member, threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dropdown handling
|
||||
if let TickResult::Action(name) = self.context_menu.tick(par.layout, &mut self.parser_state)?
|
||||
&& let (Some(action), Some(action_name), Some(side), Some(value)) = {
|
||||
let mut s = name.splitn(4, ';');
|
||||
(s.next(), s.next(), s.next(), s.next())
|
||||
} {
|
||||
if let TickResult::Action(name) = self.context_menu.tick(par.layout, &mut self.parser_state)? {
|
||||
let parts = name.split(';').collect::<Vec<_>>();
|
||||
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
||||
let action_mut = get_action_mut(cur_profile, action_name);
|
||||
let side_mut = if side == "right" {
|
||||
&mut action_mut.right
|
||||
} else {
|
||||
&mut action_mut.left
|
||||
};
|
||||
|
||||
match action {
|
||||
"clear" => {
|
||||
*side_mut = None;
|
||||
}
|
||||
"subpath" => {
|
||||
apply_subpath(side_mut, side, value, self.controller_profile);
|
||||
}
|
||||
"comp" => {
|
||||
apply_comp(side_mut, side, value);
|
||||
}
|
||||
"click" => match value {
|
||||
"triple" => {
|
||||
action_mut.triple_click = Some(true);
|
||||
action_mut.double_click = None;
|
||||
match parts.as_slice() {
|
||||
[action, action_name, side, value] => {
|
||||
let action_mut = get_action_mut(cur_profile, action_name);
|
||||
|
||||
match *action {
|
||||
"clear" => {
|
||||
*action_binding_mut(action_mut, side) = None;
|
||||
}
|
||||
"subpath" => {
|
||||
apply_subpath(
|
||||
action_binding_mut(action_mut, side),
|
||||
action_name,
|
||||
side,
|
||||
value,
|
||||
self.controller_profile,
|
||||
);
|
||||
}
|
||||
"comp" => {
|
||||
apply_comp(action_binding_mut(action_mut, side), side, value);
|
||||
}
|
||||
"click" => apply_click_count(action_mut, value),
|
||||
_ => log::warn!("Unknown action {action}"),
|
||||
}
|
||||
"double" => {
|
||||
action_mut.triple_click = None;
|
||||
action_mut.double_click = Some(true);
|
||||
self.refresh(par.layout)?;
|
||||
}
|
||||
[kind, action_name, output_side, member_idx, value] => {
|
||||
let (Ok(output_side), Ok(member_idx)) = (XrInputSide::try_from(*output_side), member_idx.parse::<usize>())
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let action_mut = get_action_mut(cur_profile, action_name);
|
||||
let Some(member) = action_chord_mut(action_mut, output_side)
|
||||
.as_mut()
|
||||
.and_then(|members| members.get_mut(member_idx))
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
match *kind {
|
||||
"chord_hand" => {
|
||||
if let Ok(side) = XrInputSide::try_from(*value) {
|
||||
apply_chord_hand(member, side, self.controller_profile);
|
||||
}
|
||||
}
|
||||
"chord_subpath" => {
|
||||
if let Ok(subpath) = XrInputSubpathKind::try_from(*value) {
|
||||
apply_chord_subpath(member, subpath, self.controller_profile);
|
||||
}
|
||||
}
|
||||
"chord_comp" => {
|
||||
if let Ok(component) = XrInputComponent::try_from(*value) {
|
||||
apply_chord_component(member, component);
|
||||
}
|
||||
}
|
||||
_ => log::warn!("Unknown chord action {kind}"),
|
||||
}
|
||||
_ => {
|
||||
action_mut.triple_click = None;
|
||||
action_mut.double_click = None;
|
||||
}
|
||||
},
|
||||
_ => log::warn!("Unknown action {action}"),
|
||||
self.refresh(par.layout)?;
|
||||
}
|
||||
_ => log::warn!("Malformed bindings context action: {name}"),
|
||||
}
|
||||
|
||||
self.refresh(par.layout)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -157,7 +217,7 @@ impl View {
|
||||
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/bindings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/bindings.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
@@ -228,7 +288,7 @@ impl View {
|
||||
parser_state: &mut self.parser_state,
|
||||
doc_params: &ParseDocumentParams {
|
||||
globals: self.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/bindings.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/bindings.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
layout,
|
||||
@@ -413,6 +473,172 @@ fn input_controls_for_action(
|
||||
},
|
||||
)?;
|
||||
|
||||
if &*action != "scroll" {
|
||||
if is_side_agnostic_action(action.as_ref()) {
|
||||
chord_controls_for_output(
|
||||
mp,
|
||||
parent,
|
||||
&action,
|
||||
XrInputSide::Left,
|
||||
current.left_chord.as_deref(),
|
||||
click_type,
|
||||
profile,
|
||||
false,
|
||||
)?;
|
||||
} else {
|
||||
for output_side in [XrInputSide::Left, XrInputSide::Right] {
|
||||
if profile.find_userpath(output_side).is_none() {
|
||||
continue;
|
||||
}
|
||||
let chord = if matches!(output_side, XrInputSide::Right) {
|
||||
current.right_chord.as_deref()
|
||||
} else {
|
||||
current.left_chord.as_deref()
|
||||
};
|
||||
chord_controls_for_output(mp, parent, &action, output_side, chord, click_type, profile, true)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_side_agnostic_action(action: &str) -> bool {
|
||||
matches!(action, "show_hide" | "toggle_dashboard")
|
||||
}
|
||||
|
||||
fn chord_controls_for_output(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
action: &Rc<str>,
|
||||
output_side: XrInputSide,
|
||||
members: Option<&[OpenXrInputChordMember]>,
|
||||
click_type: ClickType,
|
||||
profile: &XrControllerProfile,
|
||||
show_output_side: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
let header = horiz_cell(mp.layout, parent)?;
|
||||
|
||||
if show_output_side {
|
||||
wgui_simple::create_icon(
|
||||
mp.layout,
|
||||
header,
|
||||
Vec2::new(24.0, 24.0),
|
||||
AssetPathRef::BuiltIn(&format!("dashboard/hand_{}.svg", output_side.as_ref())),
|
||||
)?;
|
||||
wgui_simple::create_label(mp.layout, header, side_translation(output_side))?;
|
||||
}
|
||||
|
||||
wgui_simple::create_label(
|
||||
mp.layout,
|
||||
header,
|
||||
Translation::from_translation_key("APP_SETTINGS.BINDINGS.CHORD"),
|
||||
)?;
|
||||
clicks_dropdown(mp, header, action.clone(), click_type)?;
|
||||
|
||||
let tasks = mp.tasks.clone();
|
||||
let action_for_add = action.clone();
|
||||
wgui_simple::create_button(wgui_simple::CreateButtonParams {
|
||||
id_parent: header,
|
||||
layout: mp.layout,
|
||||
content: Translation::from_translation_key("APP_SETTINGS.BINDINGS.CHORD_ADD_INPUT"),
|
||||
icon_builtin: AssetPathRef::BuiltIn("dashboard/add.svg"),
|
||||
on_click: Rc::new(move |_common, _event| {
|
||||
tasks.push(Task::AddChordMember(action_for_add.clone(), output_side));
|
||||
Ok(())
|
||||
}),
|
||||
})?;
|
||||
|
||||
for (member_idx, member) in members.unwrap_or_default().iter().enumerate() {
|
||||
chord_member_controls(mp, parent, action, output_side, member_idx, member, profile)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn chord_member_controls(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
action: &Rc<str>,
|
||||
output_side: XrInputSide,
|
||||
member_idx: usize,
|
||||
member: &OpenXrInputChordMember,
|
||||
profile: &XrControllerProfile,
|
||||
) -> anyhow::Result<()> {
|
||||
let row = horiz_cell(mp.layout, parent)?;
|
||||
let parsed = ParsedOpenXrInputPath::try_from(member.path())
|
||||
.log_warn(member.path())
|
||||
.ok();
|
||||
let physical_side = parsed.as_ref().map(|x| x.side).unwrap_or(output_side);
|
||||
|
||||
chord_hand_dropdown(mp, row, action.clone(), output_side, member_idx, profile, physical_side)?;
|
||||
|
||||
let available_subpaths: Rc<[XrInputSubpathKind]> = profile
|
||||
.find_userpath(physical_side)
|
||||
.map(|user_path| {
|
||||
user_path
|
||||
.paths
|
||||
.iter()
|
||||
.filter(|x| !x.kind.get_bool("Hidden").unwrap_or_default())
|
||||
.map(|x| x.kind)
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
chord_subpath_dropdown(
|
||||
mp,
|
||||
row,
|
||||
action.clone(),
|
||||
output_side,
|
||||
member_idx,
|
||||
available_subpaths,
|
||||
parsed.as_ref().map(|x| x.subpath),
|
||||
)?;
|
||||
|
||||
let available_components: Rc<[XrInputComponent]> = parsed
|
||||
.as_ref()
|
||||
.and_then(|parsed| {
|
||||
profile
|
||||
.find_userpath(parsed.side)
|
||||
.and_then(|user_path| user_path.find_subpath(parsed.subpath))
|
||||
})
|
||||
.map(|subpath| subpath.components)
|
||||
.unwrap_or_default()
|
||||
.into();
|
||||
|
||||
chord_component_dropdown(
|
||||
mp,
|
||||
row,
|
||||
action.clone(),
|
||||
output_side,
|
||||
member_idx,
|
||||
available_components,
|
||||
parsed.and_then(|x| x.component),
|
||||
)?;
|
||||
|
||||
let tasks = mp.tasks.clone();
|
||||
let action_for_remove = action.clone();
|
||||
wgui_simple::create_button(wgui_simple::CreateButtonParams {
|
||||
id_parent: row,
|
||||
layout: mp.layout,
|
||||
content: Translation::from_raw_text(""),
|
||||
icon_builtin: AssetPathRef::BuiltIn("dashboard/trash.svg"),
|
||||
on_click: Rc::new(move |_common, _event| {
|
||||
tasks.push(Task::RemoveChordMember(
|
||||
action_for_remove.clone(),
|
||||
output_side,
|
||||
member_idx,
|
||||
));
|
||||
Ok(())
|
||||
}),
|
||||
})?;
|
||||
|
||||
// put threshold slider on its own row
|
||||
if parsed.and_then(|x| x.component).is_some_and(|x| x.is_analog()) {
|
||||
chord_threshold_slider(mp, parent, action.clone(), output_side, member_idx, member.threshold())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -437,13 +663,6 @@ fn input_controls_for_hand(mp: &mut MacroParams, par: InputControlsForHandParams
|
||||
|
||||
let parent = horiz_cell(mp.layout, par.parent)?;
|
||||
|
||||
let available_components: Rc<[XrInputComponent]> = current
|
||||
.as_ref()
|
||||
.and_then(|par| user_path.find_subpath(par.subpath))
|
||||
.map(|subp| subp.components)
|
||||
.unwrap_or_default()
|
||||
.into();
|
||||
|
||||
let available_subpaths: Rc<[XrInputSubpathKind]> = user_path
|
||||
.paths
|
||||
.iter()
|
||||
@@ -460,23 +679,33 @@ fn input_controls_for_hand(mp: &mut MacroParams, par: InputControlsForHandParams
|
||||
current.as_ref().map(|x| x.subpath),
|
||||
)?;
|
||||
|
||||
if &**par.action == "scroll" {
|
||||
clicks_dropdown(mp, parent, par.action.clone(), par.click_type)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let available_components: Rc<[XrInputComponent]> = current
|
||||
.as_ref()
|
||||
.and_then(|par| user_path.find_subpath(par.subpath))
|
||||
.map(|subp| subp.components)
|
||||
.unwrap_or_default()
|
||||
.into();
|
||||
|
||||
if !component_dropdown(
|
||||
mp,
|
||||
parent,
|
||||
par.action.clone(),
|
||||
par.side,
|
||||
available_components,
|
||||
current.as_ref().map(|x| x.component),
|
||||
current.and_then(|x| x.component),
|
||||
)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
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.and_then(|x| x.component)
|
||||
&& component.is_analog()
|
||||
&& &**par.action != "scroll"
|
||||
// hax
|
||||
{
|
||||
threshold_slider(mp, parent, par.action.clone(), par.side, par.threshold)?;
|
||||
}
|
||||
@@ -501,7 +730,7 @@ fn subpath_dropdown(
|
||||
mp.layout,
|
||||
parent,
|
||||
Vec2::new(32.0, 32.0),
|
||||
AssetPath::BuiltIn(&format!("dashboard/hand_{}.svg", side.as_ref())),
|
||||
AssetPathRef::BuiltIn(&format!("dashboard/hand_{}.svg", side.as_ref())),
|
||||
)?;
|
||||
|
||||
let current_text = current
|
||||
@@ -552,6 +781,181 @@ fn clicks_dropdown(mp: &mut MacroParams, parent: WidgetID, action: Rc<str>, curr
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn side_translation(side: XrInputSide) -> Translation {
|
||||
Translation::from_translation_key(match side {
|
||||
XrInputSide::Left => "APP_SETTINGS.BINDINGS.LEFT",
|
||||
XrInputSide::Right => "APP_SETTINGS.BINDINGS.RIGHT",
|
||||
})
|
||||
}
|
||||
|
||||
fn chord_hand_dropdown(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
action: Rc<str>,
|
||||
output_side: XrInputSide,
|
||||
member_idx: usize,
|
||||
profile: &XrControllerProfile,
|
||||
current: XrInputSide,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("tooltip", "APP_SETTINGS.BINDINGS.CHORD_INPUT_HAND");
|
||||
params.insert("min_width", "100");
|
||||
|
||||
let cells = [XrInputSide::Left, XrInputSide::Right]
|
||||
.into_iter()
|
||||
.filter(|side| profile.find_userpath(*side).is_some())
|
||||
.map(|side| {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(
|
||||
format!(
|
||||
"chord_hand;{};{};{};{}",
|
||||
action,
|
||||
output_side.as_ref(),
|
||||
member_idx,
|
||||
side.as_ref()
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
title: side_translation(side),
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
create_dropdown_with_cells(mp, parent, params, side_translation(current), cells)
|
||||
}
|
||||
|
||||
fn chord_subpath_dropdown(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
action: Rc<str>,
|
||||
output_side: XrInputSide,
|
||||
member_idx: usize,
|
||||
available: Rc<[XrInputSubpathKind]>,
|
||||
current: Option<XrInputSubpathKind>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("tooltip", "APP_SETTINGS.BINDINGS.SUBPATH");
|
||||
params.insert("min_width", "100");
|
||||
|
||||
let current_text = current
|
||||
.map(|subpath| subpath.translation())
|
||||
.unwrap_or_else(|| Translation::from_translation_key("APP_SETTINGS.OPTION.NONE"));
|
||||
let cells = available
|
||||
.iter()
|
||||
.map(|subpath| {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(
|
||||
format!(
|
||||
"chord_subpath;{};{};{};{}",
|
||||
action,
|
||||
output_side.as_ref(),
|
||||
member_idx,
|
||||
subpath.as_ref()
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
title: subpath.translation(),
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
create_dropdown_with_cells(mp, parent, params, current_text, cells)
|
||||
}
|
||||
|
||||
fn chord_component_dropdown(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
action: Rc<str>,
|
||||
output_side: XrInputSide,
|
||||
member_idx: usize,
|
||||
available: Rc<[XrInputComponent]>,
|
||||
current: Option<XrInputComponent>,
|
||||
) -> anyhow::Result<bool> {
|
||||
if available.is_empty() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("text", "・");
|
||||
params.insert("tooltip", "APP_SETTINGS.BINDINGS.COMPONENT");
|
||||
params.insert("min_width", "100");
|
||||
|
||||
let current_text = current
|
||||
.map(|component| component.translation())
|
||||
.unwrap_or_else(|| Translation::from_raw_text_rc(Default::default()));
|
||||
let cells = available
|
||||
.iter()
|
||||
.map(|component| {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(
|
||||
format!(
|
||||
"chord_comp;{};{};{};{}",
|
||||
action,
|
||||
output_side.as_ref(),
|
||||
member_idx,
|
||||
component.as_ref()
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
title: component.translation(),
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
create_dropdown_with_cells(mp, parent, params, current_text, cells)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn chord_threshold_slider(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
action: Rc<str>,
|
||||
output_side: XrInputSide,
|
||||
member_idx: usize,
|
||||
current: Option<[f32; 2]>,
|
||||
) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
|
||||
let current = current.unwrap_or(DEFAULT_BUTTON_THRESHOLDS);
|
||||
|
||||
let mut params = TemplateParams::new();
|
||||
params.insert("id", &id);
|
||||
params.insert("tooltip", "APP_SETTINGS.BINDINGS.THRESHOLD");
|
||||
params.insert_str("value", format!("{:.2}", current[0]));
|
||||
params.insert_str("value2", format!("{:.2}", current[1]));
|
||||
params.insert("min", "0.0");
|
||||
params.insert("max", "1.0");
|
||||
params.insert("step", "0.1");
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "ThresholdSlider", mp.layout, parent, params)?;
|
||||
|
||||
let slider = mp.parser_state.fetch_component_as::<ComponentSlider>(&id)?;
|
||||
slider.on_value_changed(Box::new({
|
||||
let tasks = mp.tasks.clone();
|
||||
move |_common, e| {
|
||||
let threshold_idx = if matches!(e.index, wgui::components::slider::ValueIndex::Primary) {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
tasks.push(Task::UpdateChordThreshold(
|
||||
action.clone(),
|
||||
output_side,
|
||||
member_idx,
|
||||
threshold_idx,
|
||||
e.value,
|
||||
));
|
||||
}
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn threshold_slider(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
@@ -594,67 +998,63 @@ fn threshold_slider(
|
||||
fn create_dropdown<B: 'static + BindingsDropdown>(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
mut params: TemplateParams,
|
||||
params: TemplateParams,
|
||||
action: Rc<str>,
|
||||
side: XrInputSide,
|
||||
current_text: Translation,
|
||||
available: Rc<[B]>,
|
||||
) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
params.insert("id", &id);
|
||||
let mut cells = available
|
||||
.iter()
|
||||
.map(|item| {
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(item.action_str(&action, side).into()),
|
||||
title: item.translation(),
|
||||
..Default::default()
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
mp.parser_state
|
||||
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
|
||||
|
||||
{
|
||||
let mut label = mp
|
||||
.parser_state
|
||||
.fetch_widget_as::<WidgetLabel>(&mp.layout.state, &format!("{id}_value"))?;
|
||||
label.set_text_simple(&mut mp.layout.state.globals.get(), current_text);
|
||||
if let Some(action_str) = B::clear_str(&action, side) {
|
||||
cells.insert(
|
||||
0,
|
||||
context_menu::Cell::Button(context_menu::Button {
|
||||
action_name: Some(action_str.into()),
|
||||
title: Translation::from_translation_key("APP_SETTINGS.OPTION.NONE"),
|
||||
..Default::default()
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||
btn.on_click(Rc::new({
|
||||
let tasks = mp.tasks.clone();
|
||||
let available = available.clone();
|
||||
move |_common, e: ButtonClickEvent| {
|
||||
let mut cells = available
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let title = item.translation();
|
||||
create_dropdown_with_cells(mp, parent, params, current_text, cells)
|
||||
}
|
||||
|
||||
context_menu::Cell {
|
||||
action_name: Some(item.action_str(&action, side)),
|
||||
title,
|
||||
tooltip: None,
|
||||
attribs: vec![],
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if let Some(action_str) = B::clear_str(&action, side) {
|
||||
cells.insert(
|
||||
0,
|
||||
context_menu::Cell {
|
||||
action_name: Some(action_str),
|
||||
title: Translation::from_translation_key("APP_SETTINGS.OPTION.NONE"),
|
||||
tooltip: None,
|
||||
attribs: vec![],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
tasks.push(Task::OpenContextMenu(e.mouse_pos_absolute.unwrap_or_default(), cells));
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
fn create_dropdown_with_cells(
|
||||
mp: &mut MacroParams,
|
||||
parent: WidgetID,
|
||||
params: TemplateParams,
|
||||
current_text: Translation,
|
||||
cells: Vec<context_menu::Cell>,
|
||||
) -> anyhow::Result<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
let tasks = mp.tasks.clone();
|
||||
wgui_simple::mount_dropdown(wgui_simple::MountDropdownParams {
|
||||
layout: mp.layout,
|
||||
parser_state: mp.parser_state,
|
||||
doc_params: mp.doc_params,
|
||||
parent,
|
||||
id,
|
||||
params,
|
||||
current_text,
|
||||
cells,
|
||||
on_open: Box::new(move |pos, cells| tasks.push(Task::OpenContextMenu(pos, cells))),
|
||||
})
|
||||
}
|
||||
|
||||
fn apply_subpath(
|
||||
side_mut: &mut Option<OneOrMany<String>>,
|
||||
action_name: &str,
|
||||
side_str: &str,
|
||||
subpath_str: &str,
|
||||
profile: &XrControllerProfile,
|
||||
@@ -665,6 +1065,12 @@ fn apply_subpath(
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if action_name == "scroll" {
|
||||
*side_mut = Some(OneOrMany::One(format!("/user/hand/{side_str}/input/{subpath_str}")));
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(subpath_obj) = profile.find_userpath(side).and_then(|p| p.find_subpath(subpath)) else {
|
||||
return;
|
||||
};
|
||||
@@ -677,11 +1083,12 @@ fn apply_subpath(
|
||||
return;
|
||||
};
|
||||
|
||||
let mut parsed_compo = parsed.component;
|
||||
if !subpath_obj.components.contains(&parsed_compo) {
|
||||
parsed_compo = *subpath_obj.components.first().unwrap();
|
||||
let parsed_compo = parsed.component.unwrap_or(*subpath_obj.components.first().unwrap());
|
||||
if subpath_obj.components.contains(&parsed_compo) {
|
||||
parsed_compo
|
||||
} else {
|
||||
*subpath_obj.components.first().unwrap()
|
||||
}
|
||||
parsed_compo
|
||||
} else {
|
||||
*subpath_obj.components.first().unwrap()
|
||||
};
|
||||
@@ -710,3 +1117,169 @@ fn apply_comp(side_mut: &mut Option<OneOrMany<String>>, side: &str, comp: &str)
|
||||
|
||||
*side_mut = Some(OneOrMany::One(format!("/user/hand/{side}/input/{subpath}/{comp}")));
|
||||
}
|
||||
|
||||
fn action_chord_mut(
|
||||
action: &mut OpenXrInputAction,
|
||||
output_side: XrInputSide,
|
||||
) -> &mut Option<Vec<OpenXrInputChordMember>> {
|
||||
match output_side {
|
||||
XrInputSide::Left => &mut action.left_chord,
|
||||
XrInputSide::Right => &mut action.right_chord,
|
||||
}
|
||||
}
|
||||
|
||||
fn action_binding_mut<'a>(action: &'a mut OpenXrInputAction, side: &str) -> &'a mut Option<OneOrMany<String>> {
|
||||
if side == "right" {
|
||||
&mut action.right
|
||||
} else {
|
||||
&mut action.left
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_click_count(action: &mut OpenXrInputAction, value: &str) {
|
||||
match value {
|
||||
"triple" => {
|
||||
action.triple_click = Some(true);
|
||||
action.double_click = None;
|
||||
}
|
||||
"double" => {
|
||||
action.triple_click = None;
|
||||
action.double_click = Some(true);
|
||||
}
|
||||
_ => {
|
||||
action.triple_click = None;
|
||||
action.double_click = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_chord_member(profile: &XrControllerProfile, preferred_side: XrInputSide) -> Option<OpenXrInputChordMember> {
|
||||
let other_side = match preferred_side {
|
||||
XrInputSide::Left => XrInputSide::Right,
|
||||
XrInputSide::Right => XrInputSide::Left,
|
||||
};
|
||||
|
||||
for side in [preferred_side, other_side] {
|
||||
let Some(user_path) = profile.find_userpath(side) else {
|
||||
continue;
|
||||
};
|
||||
let Some(subpath) = user_path
|
||||
.paths
|
||||
.iter()
|
||||
.find(|subpath| !subpath.kind.get_bool("Hidden").unwrap_or_default() && !subpath.components.is_empty())
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let component = *subpath.components.first()?;
|
||||
return Some(OpenXrInputChordMember::Path(format!(
|
||||
"/user/hand/{}/input/{}/{}",
|
||||
side.as_ref(),
|
||||
subpath.kind.as_ref(),
|
||||
component.as_ref()
|
||||
)));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_chord_member_path(member: &mut OpenXrInputChordMember, path: String, component: XrInputComponent) {
|
||||
let threshold = if component.is_analog() {
|
||||
member.threshold()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
*member = if threshold.is_some() {
|
||||
OpenXrInputChordMember::Detailed { path, threshold }
|
||||
} else {
|
||||
OpenXrInputChordMember::Path(path)
|
||||
};
|
||||
}
|
||||
|
||||
fn set_chord_member_threshold(member: &mut OpenXrInputChordMember, threshold: [f32; 2]) {
|
||||
*member = OpenXrInputChordMember::Detailed {
|
||||
path: member.path().to_owned(),
|
||||
threshold: Some(threshold),
|
||||
};
|
||||
}
|
||||
|
||||
fn apply_chord_hand(member: &mut OpenXrInputChordMember, side: XrInputSide, profile: &XrControllerProfile) {
|
||||
let parsed = ParsedOpenXrInputPath::try_from(member.path()).ok();
|
||||
let Some(user_path) = profile.find_userpath(side) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let subpath = parsed
|
||||
.and_then(|parsed| user_path.find_subpath(parsed.subpath))
|
||||
.filter(|subpath| !subpath.kind.get_bool("Hidden").unwrap_or_default() && !subpath.components.is_empty())
|
||||
.or_else(|| {
|
||||
user_path
|
||||
.paths
|
||||
.iter()
|
||||
.find(|subpath| !subpath.kind.get_bool("Hidden").unwrap_or_default() && !subpath.components.is_empty())
|
||||
});
|
||||
let Some(subpath) = subpath else {
|
||||
return;
|
||||
};
|
||||
|
||||
let component = parsed
|
||||
.and_then(|parsed| parsed.component)
|
||||
.filter(|component| subpath.components.contains(component))
|
||||
.unwrap_or(subpath.components[0]);
|
||||
let path = format!(
|
||||
"/user/hand/{}/input/{}/{}",
|
||||
side.as_ref(),
|
||||
subpath.kind.as_ref(),
|
||||
component.as_ref()
|
||||
);
|
||||
set_chord_member_path(member, path, component);
|
||||
}
|
||||
|
||||
fn apply_chord_subpath(
|
||||
member: &mut OpenXrInputChordMember,
|
||||
subpath: XrInputSubpathKind,
|
||||
profile: &XrControllerProfile,
|
||||
) {
|
||||
let Ok(parsed) = ParsedOpenXrInputPath::try_from(member.path()) else {
|
||||
return;
|
||||
};
|
||||
let Some(subpath_obj) = profile
|
||||
.find_userpath(parsed.side)
|
||||
.and_then(|user_path| user_path.find_subpath(subpath))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(first_component) = subpath_obj.components.first().copied() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let component = if let Some(comp) = parsed.component {
|
||||
if subpath_obj.components.contains(&comp) {
|
||||
comp
|
||||
} else {
|
||||
first_component
|
||||
}
|
||||
} else {
|
||||
first_component
|
||||
};
|
||||
let path = format!(
|
||||
"/user/hand/{}/input/{}/{}",
|
||||
parsed.side.as_ref(),
|
||||
subpath.as_ref(),
|
||||
component.as_ref()
|
||||
);
|
||||
set_chord_member_path(member, path, component);
|
||||
}
|
||||
|
||||
fn apply_chord_component(member: &mut OpenXrInputChordMember, component: XrInputComponent) {
|
||||
let Ok(parsed) = ParsedOpenXrInputPath::try_from(member.path()) else {
|
||||
return;
|
||||
};
|
||||
let path = format!(
|
||||
"/user/hand/{}/input/{}/{}",
|
||||
parsed.side.as_ref(),
|
||||
parsed.subpath.as_ref(),
|
||||
component.as_ref()
|
||||
);
|
||||
set_chord_member_path(member, path, component);
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
use wgui::color::WguiColorName;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
@@ -93,7 +93,7 @@ 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"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/color_palettes.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
views::{ViewTrait, ViewUpdateParams},
|
||||
};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
@@ -32,6 +32,21 @@ enum Task {
|
||||
ActionClicked(&'static str),
|
||||
}
|
||||
|
||||
pub fn get_entries_yes_no() -> Vec<ButtonEntry> {
|
||||
vec![
|
||||
ButtonEntry {
|
||||
content: Translation::from_translation_key("YES"),
|
||||
icon: "@/dashboard/check.svg",
|
||||
action: "yes",
|
||||
},
|
||||
ButtonEntry {
|
||||
content: Translation::from_translation_key("NO"),
|
||||
icon: "@/dashboard/cancel.svg",
|
||||
action: "no",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub struct View {
|
||||
tasks: Tasks<Task>,
|
||||
|
||||
@@ -45,13 +60,20 @@ pub struct View {
|
||||
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/dialog_box.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/dialog_box.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewTrait for View {
|
||||
fn update(&mut self, _par: &mut ViewUpdateParams) -> anyhow::Result<()> {
|
||||
self.tick();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn tick(&mut self) {
|
||||
for task in self.tasks.drain() {
|
||||
match task {
|
||||
Task::ActionClicked(action) => {
|
||||
@@ -65,11 +87,8 @@ impl ViewTrait for View {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn new(
|
||||
layout: &mut Layout,
|
||||
id_parent: WidgetID,
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
use glam::Vec2;
|
||||
use std::path::PathBuf;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
@@ -59,7 +59,7 @@ pub struct View {
|
||||
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/download_file.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/download_file.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ impl ViewTrait for View {
|
||||
par.layout,
|
||||
self.id_loading_parent,
|
||||
Vec2::splat(32.0),
|
||||
AssetPath::BuiltIn("dashboard/check.svg"),
|
||||
AssetPathRef::BuiltIn("dashboard/check.svg"),
|
||||
)?;
|
||||
|
||||
// "Close window" button
|
||||
@@ -114,7 +114,7 @@ impl ViewTrait for View {
|
||||
par.layout,
|
||||
self.id_loading_parent,
|
||||
Vec2::splat(32.0),
|
||||
AssetPath::BuiltIn("dashboard/error.svg"),
|
||||
AssetPathRef::BuiltIn("dashboard/error.svg"),
|
||||
)?;
|
||||
}
|
||||
Task::Close => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::{
|
||||
self,
|
||||
button::ComponentButton,
|
||||
@@ -311,7 +311,7 @@ impl ViewCommon {
|
||||
|
||||
fn get_placeholder_image(&mut self) -> anyhow::Result<&CustomGlyphData> {
|
||||
if self.img_placeholder.is_none() {
|
||||
let c = CustomGlyphData::from_assets(&self.globals, AssetPath::BuiltIn("dashboard/placeholder_cover.png"))?;
|
||||
let c = CustomGlyphData::from_assets(&self.globals, AssetPathRef::BuiltIn("dashboard/placeholder_cover.png"))?;
|
||||
self.img_placeholder = Some(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
views::{ViewTrait, ViewUpdateParams, game_cover},
|
||||
};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRef,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
@@ -82,7 +82,7 @@ impl View {
|
||||
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/game_launcher.xml"),
|
||||
path: AssetPathRef::BuiltIn("gui/view/game_launcher.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
|
||||
Loaded 100 of 301 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user