XR for Universal Blue and Fedora Atomic Desktops
vr fedora-atomic linux
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

Stable rewrite

matrixfurry.com 195adea2 eee4a255

verified
+462 -909
+14 -18
README.md
··· 1 1 <!-- SPDX-License-Identifier: CC-BY-SA-4.0 --> 2 2 <!-- Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> --> 3 3 4 - AtomicXR (axr) 5 - ============== 4 + # AtomicXR # 5 + XR for Universal Blue and Fedora Atomic Desktops. 6 6 7 - Install and manage XR applications on Fedora Atomic Desktops. 7 + This repo contains the AtomicXR core libraries and CLI. Other AtomicXR repos can be found below: 8 + - [AtomicXR Homebrew Tap](https://codeberg.org/shiloh/homebrew-atomicxr): XR packaging for Fedora Atomic. 8 9 9 - Developed and tested on [Bluefin](https://projectbluefin.io/), but should work with: 10 + AtomicXR is developed and tested on [Bluefin](https://projectbluefin.io/), but should work with: 10 11 - [Bazzite](https://bazzite.gg/) 11 12 - [Fedora Silverblue](https://fedoraproject.org/atomic-desktops/silverblue/) 12 13 - Other Fedora Atomic-based distros 13 14 14 - ## Installing 15 + ## Install ## 16 + Homebrew (reccomeneded): `brew tap shiloh/atomicxr https://codeberg.org/shiloh/homebrew-atomicxr.git; brew install atomic-xr` 15 17 16 18 > NOTE: Developed with Nushell version `0.106.0`. Lower versions are not guaranteed to work. 17 19 18 - Using the install script: 19 - - bash: `bash <(curl -s https://codeberg.org/shiloh/atomic-xr/raw/branch/main/install.sh)` 20 - - nu: `nu -c (http get https://codeberg.org/shiloh/atomic-xr/raw/branch/main/install.nu)` 21 - 22 - From this repo: 23 - 1. Install Nushell (for example with Homebrew: `brew install nushell`) 24 - 2. `nu -c "use src/atomic-xr ; atomic-xr self install --local"` 25 - 26 - ## Usage 20 + From this repo: `./install.sh` 27 21 22 + ## Usage ## 28 23 > NOTE: If you plan to use the SteamVR Lighthouse driver with: 29 24 > - Flatpak Steam 30 25 > - WiVRn without a lighthouse-tracked headset (for example if you want to use lighthouse body trackers, but don't own a lighthouse headset) 31 26 > 32 - > ..you'll have to calibrate using AtomicXR instead of Envision: `axr calibrate steamvr-lh` 27 + > ..you can calibrate using AtomicXR instead of Envision: `axr steamvr-lh calibrate` 33 28 34 29 CLI: 35 - - Configure: `axr icfg` 36 - - Apply configuration & update applications: `axr apply` 37 - - Update AtomicXR: `axr self update` 30 + - Install Envision: `axr envision install` 31 + - Update Envision: `axr envision upgrade` 32 + - Set up Steam Flatpak XR: `axr flatpak steam enable-xr` 33 + - Launch [OSC Avatar Manager](https://github.com/galister/oscavmgr): `axr oscavmgr start [babble | openxr | alvr]` (use `openxr` for WiVRn) 38 34 - List avaliable CLI functions: `axr -l` 39 35 40 36 Building Envision profiles:
+4 -14
install.nu
··· 2 2 # SPDX-License-Identifier: AGPL-3.0-only 3 3 # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 4 5 - const data: path = "~/.local/share/atomic-xr" | path expand 6 - const self: path = $data | path join "self" 7 - 8 - if ($self | path exists) { 9 - cd $self 10 - git pull 11 - } else { 12 - mkdir $data 13 - cd $data 14 - git clone https://codeberg.org/shiloh/atomic-xr self 15 - cd self 16 - } 17 - 18 - nu -c "use src/atomic-xr ; atomic-xr self install" 5 + let lib_dir = $NU_LIB_DIRS | first | path join atomic-xr 6 + rm -rf $lib_dir 7 + cp -r src/atomic-xr $lib_dir 8 + cp -f src/axr.nu ~/.local/bin/axr
+2 -2
install.sh
··· 4 4 5 5 if ! nu -v $>/dev/null; then 6 6 brew install nushell \ 7 - || echo -e "\e[35mFailed to install Nushell using Homebrew. Please install Nushell or Homebrew and re-run this script.\e[0m" 7 + || echo -e "\e[35mFailed to install Nushell using Homebrew. Please install Nushell or Homebrew, then re-run this script.\e[0m" 8 8 fi 9 9 10 10 if nu -v $>/dev/null; then 11 - nu -c "$(curl -s https://codeberg.org/shiloh/atomic-xr/raw/branch/main/install.nu)" 11 + nu ./install.nu 12 12 fi
-188
src/atomic-xr/applications.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use common.nu * 5 - use std log 6 - 7 - const repos = $data_path | path join repos 8 - 9 - def pull-or-clone [ 10 - name: string 11 - url: string 12 - branch: string 13 - ] { 14 - mkdir $repos 15 - let repo = $repos | path join $name 16 - if ($repo | path exists) { 17 - cd $repo 18 - git reset --hard # Reset manual patches 19 - git switch $branch 20 - git pull 21 - } else { 22 - git clone $url $repo 23 - cd $repo 24 - } 25 - 26 - tag-or-branch $branch 27 - } 28 - 29 - def tag-or-branch [ 30 - branch: string 31 - ] { 32 - match (open $config_path).release_channel { 33 - "stable" => (git switch --detach (git tag -l --sort=v:refname | lines | last)) 34 - "devel" => (git switch $branch) 35 - _ => (error make { 36 - msg: "Invalid release channel in config" 37 - help: "If you manually edited the config, set the release channel to either `stable` or `devel`. If you used `axr icfg`, please report this issue at: https://codeberg.org/shiloh/atomic-xr/issues" 38 - }) 39 - } 40 - } 41 - 42 - export def "install envision" [] { 43 - pull-or-clone envision "https://gitlab.com/gabmus/envision.git" main 44 - cd ($repos | path join envision) 45 - 46 - if (rpm -q openxr-libs | complete | get exit_code) != 0 { 47 - rpm-ostree install openxr-libs 48 - # TODO: Notification actions 49 - notify-send -u critical "Package Installed" "Please reboot or use `rpm-ostree ex apply-live` before attempting to launch Envision." 50 - } 51 - 52 - [ 53 - "Actions=BuildMode;" 54 - "" 55 - "[Desktop Action BuildMode]" 56 - "Exec=toolbox run --container atomic-xr @CMD_NAME@" 57 - "Name=Launch in Build Mode" 58 - ] 59 - | str join "\n" 60 - | save -a data/org.gabmus.envision.desktop.in.in 61 - 62 - container-exec { 63 - if (rpm -q rpmfusion-free-release | complete | get exit_code) != 0 { 64 - sudo dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-(rpm -E %fedora).noarch.rpm 65 - sudo dnf swap -y ffmpeg-free ffmpeg --allowerasing 66 - } 67 - 68 - [ 69 - # Envision 70 - @development-tools 71 - meson 72 - jq 73 - gtk4-devel 74 - libadwaita-devel 75 - openxr-devel 76 - mesa-libGL-devel 77 - libdrm-devel 78 - vulkan-loader-devel 79 - wayland-devel 80 - eigen3-devel 81 - ninja-build 82 - vulkan-headers 83 - vte291-devel 84 - polkit-devel 85 - cargo 86 - vte291-gtk4-devel 87 - desktop-file-utils 88 - openssl-devel 89 - 90 - # WiVRn 91 - avahi-devel 92 - avahi-glib-devel 93 - cli11-devel 94 - glslang-devel 95 - glslc 96 - gstreamer1-plugins-base-devel 97 - gstreamer1-devel 98 - ffmpeg-devel 99 - libnotify-devel 100 - libva-devel 101 - json-devel 102 - x264-devel 103 - pipewire-devel 104 - cmake 105 - gcc-c++ 106 - clang19-devel 107 - openxr-devel 108 - android-tools 109 - 110 - # Monado 111 - cmake 112 - gcc-c++ 113 - glslang-devel 114 - glslc 115 - libbsd-devel 116 - libusb1 117 - libusb1-devel 118 - SDL2-devel 119 - wayland-protocols-devel 120 - openxr-devel 121 - ] | sudo dnf install -y ...$in 122 - meson setup build -Dprefix=($env.HOME)/.local --reconfigure 123 - ninja -C build 124 - ninja -C build install 125 - } 126 - } 127 - 128 - def brewed [application: string] { 129 - (brew ls $application | complete).exit_code == 0 130 - } 131 - 132 - def install-not-brewed [application: string] { 133 - if not (brewed $application) { 134 - brew install $application 135 - } 136 - } 137 - 138 - def uninstall-brewed [application: string] { 139 - if (brewed $application) { 140 - brew uninstall $application 141 - } 142 - } 143 - 144 - export def "uninstall envision" [] { 145 - rm -f ~/.local/bin/envision ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/bin/envision 146 - } 147 - 148 - export def "install wlx-overlay-s" [] { 149 - install-not-brewed wlx-overlay-s 150 - } 151 - 152 - export def "uninstall wlx-overlay-s" [] { 153 - uninstall-brewed wlx-overlay-s 154 - } 155 - 156 - export def "install wayvr-dashboard" [] { 157 - install-not-brewed wayvr-dashboard 158 - } 159 - 160 - export def "uninstall wayvr-dashboard" [] { 161 - uninstall-brewed wayr-dashboard 162 - } 163 - 164 - export def "install motoc" [] { 165 - install-not-brewed motoc 166 - } 167 - 168 - export def "uninstall motoc" [] { 169 - uninstall-brewed motoc 170 - } 171 - 172 - export def "install oscavmgr" [] { 173 - install-not-brewed vrc-advert 174 - install-not-brewed oscavmgr 175 - } 176 - 177 - export def "uninstall oscavmgr" [] { 178 - uninstall-brewed vrc-advert 179 - uninstall-brewed oscavmgr 180 - } 181 - 182 - export def "install stardust-xr" [] { 183 - log warning "Stardust XR: Install not implemented. Please see https://stardustxr.org/docs/get-started/manual for installation instructions, or wait for it to be implemented in AtomicXR." 184 - } 185 - 186 - export def "uninstall stardust-xr" [] { 187 - log debug "Stardust XR: Not implemented" 188 - }
+12
src/atomic-xr/bin/oscavmgr-launch.sh
··· 1 + #!/usr/bin/env bash 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 + # 5 + # Portions of this file are derived from OscAvMgr, which is licensed under the MIT License 6 + # Copyright (c) 2023 galister 7 + 8 + trap 'jobs -p | xargs kill' EXIT 9 + 10 + VrcAdvert OscAvMgr 9402 9002 --tracking & 11 + 12 + oscavmgr "${@}"
-18
src/atomic-xr/common.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - 6 - export const version = 5 7 - 8 - export const data_path: path = "~/.local/share/atomic-xr" | path expand 9 - export const config_path: path = "~/.config/atomic-xr.toml" | path expand 10 - export const envision_config_path: path = "~/.config/envision/envision.json" | path expand 11 - 12 - export def container-exec [ 13 - block: closure 14 - --environment (-e): record = {} 15 - ] { 16 - try {log debug $"Running in container: (view source $block)"} 17 - toolbox run --container=atomic-xr nu -c $"with-env ($environment) (view source $block)" 18 - }
+235
src/atomic-xr/envision.nu
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 + 4 + const repo = "~/.local/share/atomic-xr/envision" | path expand 5 + const envision_config_path = "~/.config/envision/envision.json" | path expand 6 + 7 + use std log 8 + 9 + export def install [] { 10 + distrobox create envision --no-entry -Y -i registry.fedoraproject.org/fedora-toolbox:latest 11 + distrobox enter envision -- sudo dnf install -y nu 12 + upgrade 13 + log info "Successfully installed Envision" 14 + } 15 + 16 + export def uninstall [] { 17 + try {distrobox rm -f envision} 18 + rm -f ~/.local/bin/envision ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/bin/envision 19 + log info "Successfully uninstalled Envision" 20 + } 21 + 22 + export def upgrade [] { 23 + distrobox upgrade envision 24 + 25 + mkdir ($repo | path dirname) 26 + if ($repo | path exists) { 27 + cd $repo 28 + git reset --hard # Reset manual patches 29 + git switch main 30 + git pull 31 + } else { 32 + git clone "https://gitlab.com/gabmus/envision.git" $repo 33 + cd $repo 34 + } 35 + git switch --detach (git tag -l --sort=v:refname | lines | last) 36 + 37 + if (rpm -q openxr-libs | complete | get exit_code) != 0 { 38 + rpm-ostree install openxr-libs 39 + # TODO: Notification actions 40 + notify-send -u critical "Package Installed" "Please reboot or use `rpm-ostree ex apply-live` before attempting to launch Envision." 41 + } 42 + 43 + [ 44 + "Actions=BuildMode;" 45 + "" 46 + "[Desktop Action BuildMode]" 47 + "Exec=distrobox enter envision -- @CMD_NAME@" 48 + "Name=Launch in Build Mode" 49 + ] 50 + | str join "\n" 51 + | save -a data/org.gabmus.envision.desktop.in.in 52 + 53 + { 54 + if (rpm -q rpmfusion-free-release | complete | get exit_code) != 0 { 55 + sudo dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-(rpm -E %fedora).noarch.rpm 56 + sudo dnf swap -y ffmpeg-free ffmpeg --allowerasing 57 + } 58 + 59 + sudo dnf builddep -y envision 60 + sudo dnf install -y envision-wivrn envision-monado 61 + 62 + meson setup build -Dprefix=($env.HOME)/.local --reconfigure 63 + ninja -C build 64 + ninja -C build install 65 + } 66 + | distrobox enter envision -- nu -c $"do (view source $in)" 67 + 68 + log info "Successfully upgraded Envision" 69 + } 70 + 71 + export module plugins { 72 + # Register AtomicXR envision plugins 73 + export def register [] { 74 + if ($envision_config_path | path exists) { 75 + cp -f $envision_config_path $"($envision_config_path).bak" 76 + } 77 + let envision_config = try {open $envision_config_path} catch { 78 + # TODO: Create default config file instead 79 + error make { 80 + msg: "Failed to open Envision config file" 81 + label: { 82 + text: "Failed to open file" 83 + span: (metadata $envision_config_path).span 84 + } 85 + help: "You'll need to open Envision at least once before registering plugins." 86 + } 87 + } 88 + let prefix = brew --prefix | path join bin 89 + let plugins = $envision_config.plugins 90 + | merge ( 91 + plugbuild wlx-overlay-s "WlxOverlay-S" ($prefix | path join wlx-overlay-s) "--openxr" 92 + --plugins $envision_config.plugins 93 + --screenshots ["https://github.com/galister/wlx-overlay-s/raw/guide/wlx-s.png"] 94 + --icon-url "https://github.com/galister/wlx-overlay-s/raw/main/wlx-overlay-s.svg" 95 + --homepage-url "https://github.com/galister/wlx-overlay-s" 96 + ) 97 + | merge ( 98 + plugbuild motoc "Motoc" ($prefix | path join motoc) continue 99 + --plugins $envision_config.plugins 100 + --homepage-url "https://github.com/galister/motoc" 101 + --description "Monado Tracking Origin Calibrator managed by AtomicXR" 102 + ) 103 + | merge ( 104 + plugbuild oscavmgr.project-babble "oscavmgr (Project Babble)" ~/.local/bin/oscavmgr-launch babble 105 + --plugins $envision_config.plugins 106 + --homepage-url "https://github.com/galister/oscavmgr" 107 + --description "OSC Avatar Manager (Project Babble) managed by AtomicXR" 108 + --conflicts ["oscavmgr.wivrn"] 109 + ) 110 + | merge ( 111 + plugbuild oscavmgr.wivrn "oscavmgr (WiVRn)" ~/.local/bin/oscavmgr-launch wivrn 112 + --plugins $envision_config.plugins 113 + --homepage-url "https://github.com/galister/oscavmgr" 114 + --description "OSC Avatar Manager (WiVRn) managed by AtomicXR" 115 + --conflicts ["oscavmgr.project-babble"] 116 + ) 117 + 118 + $envision_config 119 + | merge {plugins: $plugins} 120 + | save -f $envision_config_path 121 + 122 + log info "Envision plugins registered or updated successfully" 123 + } 124 + 125 + # Unegister AtomicXR envision plugins 126 + export def unregister [] { 127 + if ($envision_config_path | path exists) { 128 + cp -f $envision_config_path $"($envision_config_path).bak" 129 + } 130 + let envision_config = try {open $envision_config_path} catch { 131 + error make { 132 + msg: "Failed to open Envision config file" 133 + label: { 134 + text: "Failed to open file" 135 + span: (metadata $envision_config_path).span 136 + } 137 + help: "Envision's config file doesn't seem to exist, no AtomicXR plugins are registered." 138 + } 139 + } 140 + let plugins = $envision_config.plugins 141 + | reject -o ...(get-appids "wlx-overlay-s" "motoc" "oscavmgr.project-babble" "oscavmgr.wivrn") 142 + 143 + $envision_config 144 + | merge {plugins: $plugins} 145 + | save -f $envision_config_path 146 + 147 + log info "Envision plugins unregistered successfully" 148 + } 149 + 150 + def plugbuild [ 151 + id: string 152 + name: string 153 + exec_path: path 154 + ...args 155 + --description (-d): string 156 + --author (-a): string 157 + --icon-url (-i): string 158 + --version (-v): string 159 + --full-description (-f): string 160 + --homepage-url (-h): string 161 + --screenshots (-s): list<string> = [] 162 + --dependencies (-p): list<string> = [] # End with . for absolute id 163 + --conflicts (-c): list<string> = [] # End with . for absolute id 164 + --plugins: record # Plugin list to use instead of opening the config file 165 + ]: nothing -> record { 166 + let appid = get-appid $id 167 + 168 + log debug $"Building Envision plugin: ($id)" 169 + 170 + let description = $description | default $"($name) managed by AtomicXR" 171 + let full_description = $full_description | default $description 172 + let enabled = $plugins 173 + | default ( 174 + try { 175 + open $envision_config_path 176 + | get plugins 177 + } catch { 178 + [] 179 + } 180 + ) 181 + | transpose id data 182 + | where id == $appid 183 + | if ($in | length) == 0 { 184 + false 185 + } else { 186 + $in 187 + | get 0.data.enabled 188 + } 189 + 190 + let dependencies = get-appids ...$dependencies 191 + let conflicts = get-appids ...$conflicts 192 + 193 + {$appid: { 194 + plugin: { 195 + appid: $appid 196 + name: $"AtomicXR: ($name)" 197 + author: $author 198 + icon_url: $icon_url 199 + version: $version 200 + short_description: $description 201 + description: $full_description 202 + homepage_url: $homepage_url 203 + screenshots: $screenshots 204 + exec_url: null 205 + exec_path: $exec_path 206 + args: $args 207 + env_args: null 208 + dependencies: $dependencies 209 + conflicts: $conflicts 210 + plugin_type: "Executable" 211 + } 212 + enabled: $enabled 213 + }} 214 + } 215 + 216 + # Get absolute ids from relative 217 + def get-appid [ 218 + id: string 219 + ] { 220 + if $id ends-with "." { 221 + $id | str substring 0..-2 222 + } else { 223 + $"cc.dwagon.atomic-xr.($id)" 224 + } 225 + } 226 + 227 + def get-appids [ 228 + ...ids: string 229 + ] { 230 + $ids 231 + | each {|e| 232 + get-appid $e 233 + } 234 + } 235 + }
+75
src/atomic-xr/flatpak.nu
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 + 4 + use std log 5 + 6 + def "permissions allow" [appid: string] { 7 + flatpak override --user --filesystem="xdg-data/envision:ro" --filesystem="xdg-run/monado_comp_ipc" --filesystem="/var/lib/flatpak/app/io.github.wivrn.wivrn:ro" --filesystem="xdg-run/wivrn" --filesystem="xdg-config/openxr:ro" --filesystem="xdg-config/openvr:ro" $appid 8 + } 9 + 10 + def "permissions revoke" [appid: string] { 11 + flatpak override --user --nofilesystem="xdg-data/envision" --nofilesystem="xdg-run/monado_comp_ipc" --nofilesystem="/var/lib/flatpak/app/io.github.wivrn.wivrn" --nofilesystem="xdg-run/wivrn" --nofilesystem="xdg-config/openxr" --nofilesystem="xdg-config/openvr" $appid 12 + } 13 + 14 + export module steam { 15 + # Enable XR support for Steam Flatpak 16 + export def enable-xr [] { 17 + permissions allow com.valvesoftware.Steam 18 + 19 + if not ("~/.steam" | path exists) { 20 + ln -s ~/.var/app/com.valvesoftware.Steam/.steam ~/ 21 + log debug "Symlinked Steam Flatpak's .steam directory to ~/.steam." 22 + } else if (ls -lD ~/.steam).0.target != ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 23 + error make { 24 + msg: "Could not link Steam Flatpak's .steam directory to ~/.steam." 25 + help: "Back up or remove your existing ~/.steam directory, then run this command again." 26 + } 27 + } 28 + 29 + log info "Successfully set up Steam Flatpak XR." 30 + } 31 + 32 + # Disable XR support for Steam Flatpak 33 + export def disable-xr [] { 34 + permissions revoke com.valvesoftware.Steam 35 + 36 + if not ("~/.steam" | path exists) { 37 + log debug "~/.steam does not exist." 38 + } else if (ls -lD ~/.steam).0.target == ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 39 + rm ~/.steam 40 + if ("~/.steam.bak-axr" | path exists) { 41 + mv ~/.steam.bak-axr ~/.steam 42 + } 43 + } 44 + 45 + log info "Successfully reset Steam Flatpak XR." 46 + } 47 + } 48 + 49 + export module gaiasky { 50 + # Enable VR mode for Gaia Sky 51 + export def enable-vr [] { 52 + permissions allow space.gaiasky.GaiaSky 53 + [ 54 + (open /var/lib/flatpak/app/space.gaiasky.GaiaSky/current/active/export/share/applications/space.gaiasky.GaiaSky.desktop 55 + | str replace "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky" "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky -vr") 56 + "Actions=DesktopMode;" 57 + "" 58 + "[Desktop Action DesktopMode]" 59 + "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky" 60 + "Name=Launch in Desktop Mode" 61 + ] 62 + | str join "\n" 63 + | save -f ~/.local/share/applications/space.gaiasky.GaiaSky.desktop 64 + 65 + log info "Successfully enabled Gaia Sky's VR mode." 66 + } 67 + 68 + # Disable VR mode for Gaia Sky 69 + export def disable-vr [] { 70 + permissions revoke space.gaiasky.GaiaSky 71 + rm -f ~/.local/share/applications/space.gaiasky.GaiaSky.desktop 72 + 73 + log info "Successfully disabled Gaia Sky's VR mode." 74 + } 75 + }
-92
src/atomic-xr/generators/envision-plugin.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - use ../common.nu * 6 - 7 - # Can't use "generate" because it will cause odd interaction with the `generate` builtin 8 - export def "gen" [ 9 - id: string 10 - name: string 11 - exec_path: path 12 - ...args 13 - --description (-d): string 14 - --author (-a): string 15 - --icon-url (-i): string 16 - --version (-v): string 17 - --full-description (-f): string 18 - --homepage-url (-h): string 19 - --screenshots (-s): list<string> = [] 20 - --dependencies (-p): list<string> = [] # End with . for absolute id 21 - --conflicts (-c): list<string> = [] # End with . for absolute id 22 - --plugins: record # Plugin list to use instead of opening the config file 23 - ]: nothing -> record { 24 - let appid = get-appid $id 25 - 26 - log debug $"Generating Envision plugin: ($id)" 27 - 28 - let description = $description | default $"($name) managed by AtomicXR" 29 - let full_description = $full_description | default $description 30 - let enabled = $plugins 31 - | default ( 32 - try { 33 - open $envision_config_path 34 - | get plugins 35 - } catch { 36 - [] 37 - } 38 - ) 39 - | transpose id data 40 - | where id == $appid 41 - | if ($in | length) == 0 { 42 - false 43 - } else { 44 - $in 45 - | get 0.data.enabled 46 - } 47 - 48 - let dependencies = get-appids ...$dependencies 49 - let conflicts = get-appids ...$conflicts 50 - 51 - {$appid: { 52 - plugin: { 53 - appid: $appid 54 - name: $"AtomicXR: ($name)" 55 - author: $author 56 - icon_url: $icon_url 57 - version: $version 58 - short_description: $description 59 - description: $full_description 60 - homepage_url: $homepage_url 61 - screenshots: $screenshots 62 - exec_url: null 63 - exec_path: $exec_path 64 - args: $args 65 - env_args: null 66 - dependencies: $dependencies 67 - conflicts: $conflicts 68 - plugin_type: "Executable" 69 - } 70 - enabled: $enabled 71 - }} 72 - } 73 - 74 - # Generate absolute ids from relative 75 - export def "get-appid" [ 76 - id: string 77 - ] { 78 - if $id ends-with "." { 79 - $id | str substring 0..-2 80 - } else { 81 - $"cc.dwagon.atomic-xr.($id)" 82 - } 83 - } 84 - 85 - export def "get-appids" [ 86 - ...ids: string 87 - ] { 88 - $ids 89 - | each {|e| 90 - get-appid $e 91 - } 92 - }
+12
src/atomic-xr/homebrew.nu
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 + 4 + # Tap AtomicXR Homebrew 5 + export def tap [] { 6 + brew tap shiloh/atomicxr https://codeberg.org/shiloh/homebrew-atomicxr.git 7 + } 8 + 9 + # Untap AtomicXR Homebrew 10 + export def untap [] { 11 + brew untap shiloh/atomicxr 12 + }
+4 -220
src/atomic-xr/mod.nu
··· 1 1 # SPDX-License-Identifier: AGPL-3.0-only 2 2 # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 3 4 - use std log 5 - use common.nu * 6 - use sysconfig.nu 7 - 8 - export-env { 9 - # See https://github.com/nushell/nushell/issues/13403 10 - use std log 11 - 12 - $env.AXR_MODULE_PATH = ($NU_LIB_DIRS | first | path join atomic-xr) 13 - } 14 - 15 - export use self.nu * 16 - 17 - # Interactive configuration tool 18 - export def icfg [] { 19 - let applications = { 20 - envision: "Envision" 21 - wlx-overlay-s: "WlxOverlay-S" 22 - wayvr-dashboard: "WayVR Dashboard" 23 - motoc: "Monado Tracking Origin Calibrator" 24 - oscavmgr: "OSC Avatar Manager" 25 - stardust-xr: "Stardust XR (WIP)" 26 - } 27 - | transpose id name 28 - | input list -md name "Which applications would you like to install?" 29 - | get id 30 - 31 - let release_channel = match (input "Would you like to install stable or development releases of applicaions? [(S)table/(d)evelopment]: " | str downcase) { 32 - "s" | "stable" | "" => "stable" 33 - "d" | "development" | "dev" | "devel" => "devel" 34 - _ => (error make { 35 - msg: "Invalid input." 36 - help: "Run the command again, no config has been changed." 37 - }) 38 - } 39 - 40 - let sysconfigs = { 41 - gaiasky-flatpak-vr: "Gaia Sky Flatpak: VR Mode" 42 - steam-flatpak-permissions: "Steam Flatpak: Permissions for XR (works with WiVRn and Envision)" 43 - steam-flaptak-symlink: "Steam Flatpak: Link .steam to home directory" 44 - envision-plugins: "Envision: Register AtomicXR plugins" 45 - } 46 - | transpose id name 47 - | input list -md name "Would you like to apply any system configurations?" 48 - | get id 49 - 50 - { 51 - applications: $applications 52 - release_channel: $release_channel 53 - sysconfigs: $sysconfigs 54 - } 55 - | save -f $config_path 56 - 57 - print "Run `axr apply` to apply this configuration!" 58 - } 59 - 60 - # Open the configuration file 61 - export def "config open" [ 62 - --terminal (-t) # Open in terminal editor 63 - ] { 64 - if $terminal { 65 - run-external $env.EDITOR $config_path 66 - } else { 67 - start $config_path 68 - } 69 - } 70 - 71 - def "ask yn" [prompt: string] { 72 - loop { 73 - match (input -n 1 $"($prompt) [y/n]: " | str downcase) { 74 - "y" => (return true) 75 - "n" => (return false) 76 - _ => (log error "Invalid option, please choose `y` or `n`.") 77 - } 78 - } 79 - } 80 - 81 - # SteamVR Quick Calibration 82 - export def "calibrate steamvr-lh" [] { 83 - if (ask yn "Do you own a lighthouse-tracked HMD? (e.g. Index, Vive Pro)") { 84 - input -sn 1 "Please connect your headset and place it on the floor, then press any key to start the calibration." 85 - 86 - log info "Starting SteamVR Lighthouse calibration" 87 - 88 - # TODO: Support using native steam installation 89 - log warning "This is intended for Flatpak Steam, if you're using native Steam, please use Envision instead." 90 - log warning "If you'd like to see this functionality in AtomicXR, please open an issue on Codeberg." 91 - 92 - let vrcmd_bin: path = $"($env.HOME)/.steam/root/steamapps/common/SteamVR/bin/linux64/vrcmd" 93 - let environment = $"LD_LIBRARY_PATH=('~/.var/app/com.valvesoftware.Steam/.steam/root/steamapps/common/SteamVR/bin/linux64' | path expand)" 94 - 95 - let server = job spawn {flatpak run --command=$"($vrcmd_bin)" --env=$"($environment)" com.valvesoftware.Steam --pollposes} 96 - sleep 2sec # TODO: detect when the server is ready 97 - try { 98 - flatpak run --command=$"($vrcmd_bin)" --env=$"($environment)" com.valvesoftware.Steam --resetroomsetup 99 - } catch {|err| 100 - job kill $server 101 - error make $err 102 - } 103 - 104 - job kill $server 105 - log info "Calibration finished" 106 - } else { 107 - log info "Creating default Lighthouse Database" 108 - 109 - if not ("~/.steam/root/config/lighthouse/" | path exists) { 110 - error make { 111 - msg: "Could not find lighthouse configuration directory." 112 - help: "Make sure you have SteamVR installed, and .steam points to the correct location. You may need to select \"Symlink .steam directory\" in `axr icfg` if you're using the Steam Flatpak." 113 - } 114 - } 115 - 116 - { 117 - base_stations: [] 118 - known_objects: [] 119 - known_universes: [] 120 - revision: 1 121 - } 122 - | save -f ~/.steam/root/config/lighthouse/lighthousedb.json 123 - 124 - log info "Created default Lighthouse Database" 125 - } 126 - } 127 - 128 - # Open SteamVR's lighthouse_console 129 - # 130 - # Useful for pairing, dumping device configs, etc. 131 - export def "util steamvr-lh-console" [ 132 - ...args # Arguments to pass to lighthouse_console 133 - ] { 134 - # TODO: Support using native steam installation 135 - log warning "This is intended for Flatpak Steam, if you're using native Steam, please use Envision instead." 136 - log warning "If you'd like to see this functionality in AtomicXR, please open an issue on Codeberg." 137 - 138 - flatpak run --command=$"($env.HOME)/.steam/root/steamapps/common/SteamVR/tools/lighthouse/bin/linux64/lighthouse_console" com.valvesoftware.Steam ...$args 139 - } 140 - 141 - # Apply current configuration (and update applications) 142 - export def apply [ 143 - --sysconfigs-only (-s) 144 - --applications-only (-a) 145 - ] { 146 - if $sysconfigs_only and $applications_only { 147 - error make { 148 - msg: "Incompatible flags" 149 - label: { 150 - text: "Incompatible with --sysconfigs-only (-s)" 151 - span: (metadata $applications_only).span 152 - } 153 - help: "Only sepecify 1 of: --sysconfigs-only (-s), --applications-only (-a)" 154 - } 155 - } 156 - let config = try {open $config_path} catch { 157 - error make { 158 - msg: "Failed to open config file." 159 - help: "Create a configuration file with `axr icfg` or `axr config open`." 160 - } 161 - } 162 - 163 - if not $sysconfigs_only { 164 - const applications_path = path self ./applications.nu 165 - # HACK: `scope modules` doesn't work how you'd expect when executed from modules, so we have to do this 166 - let application_commands = nu -c $"use ($applications_path) ; scope modules | where name == applications | get 0.commands.name | to nuon" | from nuon 167 - 168 - let supported_applications = $application_commands 169 - | where $it starts-with "install " 170 - | str replace "install " "" 171 - | where {|e| $"uninstall ($e)" in $application_commands} 172 - 173 - log debug $"Supported applications: ($supported_applications | to text)" 174 - 175 - $config.applications 176 - | each {|e| 177 - if $e not-in $supported_applications { 178 - log warning $"Unkown application `($e)` found in configuration." 179 - } 180 - } 181 - 182 - $supported_applications 183 - | each {|application| 184 - if $application in $config.applications { 185 - nu -c $"use ($applications_path) ; applications install ($application)" 186 - } else { 187 - nu -c $"use ($applications_path) ; applications uninstall ($application)" 188 - } 189 - } 190 - } 191 - 192 - if not $applications_only { 193 - const sysconfigs_path = path self ./sysconfig.nu 194 - # HACK: `scope modules` doesn't work how you'd expect when executed from modules, so we have to do this 195 - let sysconfig_commands = nu -c $"use ($sysconfigs_path) ; scope modules | where name == sysconfig | get 0.commands.name | to nuon" | from nuon 196 - 197 - let supported_sysconfigs = $sysconfig_commands 198 - | where $it starts-with "enable " 199 - | str replace "enable " "" 200 - | where {|e| $"disable ($e)" in $sysconfig_commands} 201 - 202 - log debug $"Supported sysconfigs: ($supported_sysconfigs | to text)" 203 - 204 - $config.sysconfigs 205 - | each {|e| 206 - if $e not-in $supported_sysconfigs { 207 - log warning $"Unkown sysconfig `($e)` found in configuration." 208 - } 209 - } 210 - 211 - $supported_sysconfigs 212 - | each {|sysconfig| 213 - if $sysconfig in $config.sysconfigs { 214 - nu -c $"use ($sysconfigs_path) ; sysconfig enable ($sysconfig)" 215 - } else { 216 - nu -c $"use ($sysconfigs_path) ; sysconfig disable ($sysconfig)" 217 - } 218 - } 219 - } 220 - 221 - # Don't return an empty list from `each` 222 - return 223 - } 4 + export use envision.nu 5 + export use flatpak.nu 6 + export use homebrew.nu 7 + export use steamvr-lh.nu
+9
src/atomic-xr/oscavmgr.nu
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 + 4 + # Start OSC Avatar Manager and advertise it using VrcAdvert 5 + export def start [ 6 + module: string # babble, openxr (WiVRn), alvr 7 + ] { 8 + run-external (path self ./bin/oscavmgr-launch.sh) 9 + }
-197
src/atomic-xr/self.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use std log 5 - use common.nu * 6 - use applications.nu * 7 - use sysconfig.nu 8 - 9 - const self: path = $data_path | path join "self" 10 - const meta_path = $data_path | path join "metadata.nuon" 11 - 12 - # Install or update AtomicXR 13 - # 14 - # This command can only be safely used if the same module version that's loaded is the one being installed, which is never the case with `axr` 15 - export def "self install" [ 16 - --local (-l) # Install from local repo (make sure you cd to root of the repo you want to install from) 17 - --update (-u) 18 - ] { 19 - migrate 20 - 21 - mkdir $data_path 22 - 23 - if not $local { 24 - if not ($self | path exists) { 25 - git clone https://codeberg.org/shiloh/atomic-xr.git ($data_path | path join self) 26 - } 27 - cd $self 28 - git pull 29 - } 30 - 31 - log debug $"Installing from `(pwd)`" 32 - 33 - if not $update { 34 - try {toolbox create atomic-xr --distro fedora --release 42} 35 - toolbox run --container atomic-xr sudo dnf install -y nu 36 - } 37 - 38 - log debug $"AXR_MODULE_PATH: ($env.AXR_MODULE_PATH)" 39 - 40 - mkdir ~/.local/bin 41 - mkdir ($env.AXR_MODULE_PATH | path dirname) 42 - 43 - try {brew tap shiloh/atomicxr https://codeberg.org/shiloh/homebrew-atomicxr.git} 44 - try {rm -r $env.AXR_MODULE_PATH o+e> /dev/null} 45 - cp -r src/atomic-xr $env.AXR_MODULE_PATH 46 - cp -f src/axr.nu ~/.local/bin/axr 47 - chmod 744 ~/.local/bin/axr 48 - cp -f src/oscavmgr-launch.sh ~/.local/bin/oscavmgr-launch 49 - chmod 744 ~/.local/bin/oscavmgr-launch 50 - 51 - write-version $version 52 - } 53 - 54 - # Update AtomicXR 55 - export def "self update" [ 56 - --local (-l) # Install from local repo (make sure you cd to root of the repo you want to install from) 57 - ] { 58 - mkdir $data_path 59 - 60 - if not $local { 61 - if not ($self | path exists) { 62 - git clone https://codeberg.org/shiloh/atomic-xr.git ($data_path | path join self) 63 - } 64 - cd $self 65 - git pull 66 - } 67 - 68 - # This is nessesary to install any new files and do migrations from the new version 69 - # It runs the new version's `self install` instead of this version's 70 - # It always uses --local, so the repo is not pulled an extra time. 71 - nu -c $"use src/atomic-xr ; atomic-xr self install --update --local" 72 - } 73 - 74 - # Uninstall AtomicXR 75 - export def "self uninstall" [] { 76 - log info "Removing manually installed applicaions" 77 - uninstall envision 78 - 79 - log info "Disabling system configurations" 80 - sysconfig disable envision-plugins 81 - sysconfig disable steam-flaptak-symlink 82 - sysconfig disable steam-flatpak-permissions 83 - 84 - log info "Removing AtomicXR container" 85 - toolbox rm -f atomic-xr 86 - 87 - log info "Uninstalling AtomicXR" 88 - rm -r $env.AXR_MODULE_PATH 89 - rm ~/.local/bin/oscavmgr-launch 90 - rm ~/.local/bin/axr 91 - rm -r ~/.local/share/atomic-xr 92 - } 93 - 94 - # Migrate version 1 to 2 95 - def "migrate 1" [] { 96 - # Application exporting and installation was overhauled in this version 97 - log info "Removing outdated container" 98 - toolbox rm -f atomic-xr 99 - log info "Uninstalling previously installed applications (don't worry, you can reinstall them later)" 100 - rm -f ~/.local/bin/motoc ~/.local/bin/oscavmgr ~/.local/bin/wayvr-dashboard ~/.local/bin/wlx-overlay-s ~/.local/bin/envision ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/applications/org.gabmus.envision.Devel.desktop ~/.local/share/bin/envision 101 - } 102 - 103 - def "migrate 2" [] { 104 - # steam-flatpak-envision and steam-flatpak-wivrn were merged into steam-flatpak-permissions 105 - if not ($config_path | path exists) { 106 - log warning "Config file not found, migration not attempted" 107 - return 108 - } 109 - 110 - let config = open $config_path 111 - 112 - let sysconfigs = if "steam-flaptak-envision" in $config.sysconfigs or "steam-flatpak-wivrn" in $config.sysconfigs { 113 - $config.sysconfigs 114 - | where $it != "steam-flaptak-envision" and $it != "steam-flatpak-wivrn" 115 - | prepend "steam-flaptak-permissions" 116 - } else { 117 - $config.sysconfigs 118 - } 119 - 120 - $config 121 - | merge {sysconfigs: $sysconfigs} 122 - | save -f $config_path 123 - } 124 - 125 - def "migrate 3" [] { 126 - # there was a bug in `icfg` that still set these values. after that was fixed, this migration had to be run again for some people that used it 127 - migrate 2 128 - } 129 - 130 - def "migrate 4" [] { 131 - # Switched to Homebrew for wlx-overlay-s, wayvr-dashboard, oscavmgr, vrcadvert, motoc, and openxr loader 132 - log info "Removing manually installed applications: wlx-overlay-s, wayvr-dashboard, oscavmgr, vrcadvert, and motoc" 133 - rm -f ~/.local/bin/wlx-overlay-s ~/.local/bin/wayvr-dashboard ~/.local/bin/motoc ~/.local/bin/oscavmgr ~/.local/bin/VrcAdvert 134 - [ 135 - "wlx-overlay-s" 136 - "wayvr-dashboard" 137 - "motoc" 138 - "oscavmgr" 139 - "vrcadvert" 140 - ] 141 - | par-each {|e| 142 - let repo = $data_path | path join repos $e 143 - rm -rf $repo 144 - } 145 - 146 - log warning "Please run `axr apply` to apply the new configuration!" 147 - } 148 - 149 - # Migrate from installed version to current version 150 - def migrate [] { 151 - log info "Checking for migrations" 152 - 153 - if not ($data_path | path exists) { 154 - log info "AtomicXR is not installed, no migrations neessesary." 155 - return 156 - } 157 - 158 - let installed_version = if ($meta_path | path exists) { 159 - open $meta_path | get version 160 - } else { 161 - log warning "No metadata file found, assuming fresh install. No migrations attempted." 162 - return 163 - } 164 - 165 - if $installed_version == $version { 166 - log info "No migrations neessesary." 167 - return 168 - } 169 - 170 - $installed_version..($version - 1) | each {|e| 171 - log info $"Starting migration: ($e) -> ($e + 1)" 172 - match $e { 173 - 1 => (migrate 1) 174 - 2 => (migrate 2) 175 - 3 => (migrate 3) 176 - 4 => (migrate 4) 177 - _ => (error make { 178 - msg: $"Attempted to migrate from an unknown version: ($e)." 179 - help: "Please report this issue at: https://codeberg.org/shiloh/atomic-xr/issues" 180 - }) 181 - } 182 - write-version ($e + 1) 183 - log info $"Finished migration: ($e) -> ($e + 1)" 184 - } 185 - } 186 - 187 - def write-version [version: int] { 188 - if ($meta_path | path exists) { 189 - open $meta_path 190 - | merge {version: $version} 191 - | collect 192 - | save -f $meta_path 193 - } else { 194 - {version: $version} 195 - | save $meta_path 196 - } 197 - }
+74
src/atomic-xr/steamvr-lh.nu
··· 1 + # SPDX-License-Identifier: AGPL-3.0-only 2 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 + 4 + use std log 5 + 6 + def "ask yn" [prompt: string] { 7 + loop { 8 + match (input -n 1 $"($prompt) [y/n]: " | str downcase) { 9 + "y" => (return true) 10 + "n" => (return false) 11 + _ => (log error "Invalid option, please choose `y` or `n`.") 12 + } 13 + } 14 + } 15 + 16 + # SteamVR Quick Calibration 17 + export def calibrate [] { 18 + # TODO: Support using native steam installation 19 + log warning "This is intended for Flatpak Steam, if you're using native Steam, please use Envision instead." 20 + log warning "If you'd like to see native Steam functionality in AtomicXR, please open an issue on Codeberg." 21 + 22 + if (ask yn "Do you own a lighthouse-tracked HMD? (e.g. Index, Vive Pro)") { 23 + input -sn 1 "Please connect your headset and place it on the floor, then press any key to start the calibration." 24 + 25 + log info "Starting SteamVR Lighthouse calibration" 26 + 27 + let vrcmd_bin: path = $"($env.HOME)/.steam/root/steamapps/common/SteamVR/bin/linux64/vrcmd" 28 + let environment = $"LD_LIBRARY_PATH=('~/.var/app/com.valvesoftware.Steam/.steam/root/steamapps/common/SteamVR/bin/linux64' | path expand)" 29 + 30 + let server = job spawn {flatpak run --command=$"($vrcmd_bin)" --env=$"($environment)" com.valvesoftware.Steam --pollposes} 31 + sleep 2sec # TODO: detect when the server is ready 32 + try { 33 + flatpak run --command=$"($vrcmd_bin)" --env=$"($environment)" com.valvesoftware.Steam --resetroomsetup 34 + } catch {|err| 35 + job kill $server 36 + error make $err 37 + } 38 + 39 + job kill $server 40 + log info "Calibration finished" 41 + } else { 42 + log info "Creating default Lighthouse Database" 43 + 44 + if not ("~/.steam/root/config/lighthouse/" | path exists) { 45 + error make { 46 + msg: "Could not find lighthouse configuration directory." 47 + help: "Make sure you have SteamVR installed, and .steam points to the correct location. You may need to select \"Symlink .steam directory\" in `axr icfg` if you're using the Steam Flatpak." 48 + } 49 + } 50 + 51 + { 52 + base_stations: [] 53 + known_objects: [] 54 + known_universes: [] 55 + revision: 1 56 + } 57 + | save -f ~/.steam/root/config/lighthouse/lighthousedb.json 58 + 59 + log info "Created default Lighthouse Database" 60 + } 61 + } 62 + 63 + # Open SteamVR's lighthouse_console 64 + # 65 + # Useful for pairing, dumping device configs, etc. 66 + export def console [ 67 + ...args # Arguments to pass to lighthouse_console 68 + ] { 69 + # TODO: Support using native steam installation 70 + log warning "This is intended for Flatpak Steam, if you're using native Steam, please use Envision instead." 71 + log warning "If you'd like to see this functionality in AtomicXR, please open an issue on Codeberg." 72 + 73 + flatpak run --command=$"($env.HOME)/.steam/root/steamapps/common/SteamVR/tools/lighthouse/bin/linux64/lighthouse_console" com.valvesoftware.Steam ...$args 74 + }
-128
src/atomic-xr/sysconfig.nu
··· 1 - # SPDX-License-Identifier: AGPL-3.0-only 2 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 3 - 4 - use generators/envision-plugin.nu 5 - use common.nu * 6 - use std log 7 - 8 - def enable-flatpak-permissions [appid: string] { 9 - flatpak override --user --filesystem="xdg-data/envision:ro" --filesystem="xdg-run/monado_comp_ipc" --filesystem="/var/lib/flatpak/app/io.github.wivrn.wivrn:ro" --filesystem="xdg-run/wivrn" --filesystem="xdg-config/openxr:ro" --filesystem="xdg-config/openvr:ro" $appid 10 - } 11 - 12 - def disable-flatpak-permissions [appid: string] { 13 - flatpak override --user --nofilesystem="xdg-data/envision" --nofilesystem="xdg-run/monado_comp_ipc" --nofilesystem="/var/lib/flatpak/app/io.github.wivrn.wivrn" --nofilesystem="xdg-run/wivrn" --nofilesystem="xdg-config/openxr" --nofilesystem="xdg-config/openvr" $appid 14 - } 15 - 16 - export def "enable steam-flatpak-permissions" [] { 17 - enable-flatpak-permissions com.valvesoftware.Steam 18 - } 19 - 20 - export def "disable steam-flatpak-permissions" [] { 21 - disable-flatpak-permissions com.valvesoftware.Steam 22 - } 23 - 24 - export def "enable gaiasky-flatpak-vr" [] { 25 - enable-flatpak-permissions space.gaiasky.GaiaSky 26 - [ 27 - (open /var/lib/flatpak/app/space.gaiasky.GaiaSky/current/active/export/share/applications/space.gaiasky.GaiaSky.desktop 28 - | str replace "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky" "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky -vr") 29 - "Actions=DesktopMode;" 30 - "" 31 - "[Desktop Action DesktopMode]" 32 - "Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=gaiasky space.gaiasky.GaiaSky" 33 - "Name=Launch in Desktop Mode" 34 - ] 35 - | str join "\n" 36 - | save -f ~/.local/share/applications/space.gaiasky.GaiaSky.desktop 37 - } 38 - 39 - export def "disable gaiasky-flatpak-vr" [] { 40 - disable-flatpak-permissions space.gaiasky.GaiaSky 41 - rm -f ~/.local/share/applications/space.gaiasky.GaiaSky.desktop 42 - } 43 - 44 - export def "enable steam-flaptak-symlink" [] { 45 - if not ("~/.steam" | path exists) { 46 - ln -s ~/.var/app/com.valvesoftware.Steam/.steam/ ~/ 47 - return 48 - } 49 - 50 - if (ls -lD ~/.steam).0.target == ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 51 - rm -rf ~/.steam.bak-axr 52 - mv ~/.steam ~/.steam.bak-axr 53 - ln -s ~/.var/app/com.valvesoftware.Steam/.steam/ ~/ 54 - } 55 - } 56 - 57 - export def "disable steam-flaptak-symlink" [] { 58 - if not ("~/.steam" | path exists) { 59 - return 60 - } 61 - 62 - if (ls -lD ~/.steam).0.target == ("~/.var/app/com.valvesoftware.Steam/.steam/" | path expand) { 63 - rm ~/.steam 64 - if ("~/.steam.bak-axr" | path exists) { 65 - mv ~/.steam.bak-axr ~/.steam 66 - } 67 - } 68 - } 69 - 70 - export def "enable envision-plugins" [] { 71 - if ($envision_config_path | path exists) { 72 - cp -f $envision_config_path $"($envision_config_path).bak" 73 - } 74 - let envision_config = try {open $envision_config_path} catch { 75 - # TODO: Create default config file instead 76 - log warning "You'll need to open Envision at least once before plugins can be registered." 77 - return 78 - } 79 - let prefix = brew --prefix | path join bin 80 - let plugins = $envision_config.plugins 81 - | merge ( 82 - envision-plugin gen wlx-overlay-s "WlxOverlay-S" ($prefix | path join wlx-overlay-s) "--openxr" 83 - --plugins $envision_config.plugins 84 - --screenshots ["https://github.com/galister/wlx-overlay-s/raw/guide/wlx-s.png"] 85 - --icon-url "https://github.com/galister/wlx-overlay-s/raw/main/wlx-overlay-s.svg" 86 - --homepage-url "https://github.com/galister/wlx-overlay-s" 87 - ) 88 - | merge ( 89 - envision-plugin gen motoc "Motoc" ($prefix | path join motoc) continue 90 - --plugins $envision_config.plugins 91 - --homepage-url "https://github.com/galister/motoc" 92 - --description "Monado Tracking Origin Calibrator managed by AtomicXR" 93 - ) 94 - | merge ( 95 - envision-plugin gen oscavmgr.project-babble "oscavmgr (Project Babble)" ~/.local/bin/oscavmgr-launch babble 96 - --plugins $envision_config.plugins 97 - --homepage-url "https://github.com/galister/oscavmgr" 98 - --description "OSC Avatar Manager (Project Babble) managed by AtomicXR" 99 - --conflicts ["oscavmgr.wivrn"] 100 - ) 101 - | merge ( 102 - envision-plugin gen oscavmgr.wivrn "oscavmgr (WiVRn)" ~/.local/bin/oscavmgr-launch wivrn 103 - --plugins $envision_config.plugins 104 - --homepage-url "https://github.com/galister/oscavmgr" 105 - --description "OSC Avatar Manager (WiVRn) managed by AtomicXR" 106 - --conflicts ["oscavmgr.project-babble"] 107 - ) 108 - 109 - $envision_config 110 - | merge {plugins: $plugins} 111 - | save -f $envision_config_path 112 - } 113 - 114 - export def "disable envision-plugins" [] { 115 - if ($envision_config_path | path exists) { 116 - cp -f $envision_config_path $"($envision_config_path).bak" 117 - } 118 - let envision_config = try {open $envision_config_path} catch { 119 - log debug "Could not open Envision config, not attempting to remove plugins." 120 - return 121 - } 122 - let plugins = $envision_config.plugins 123 - | reject -o ...(envision-plugin get-appids "wlx-overlay-s" "motoc" "oscavmgr.project-babble" "oscavmgr.wivrn") 124 - 125 - $envision_config 126 - | merge {plugins: $plugins} 127 - | save -f $envision_config_path 128 - }
+21 -19
src/axr.nu
··· 6 6 use atomic-xr 7 7 8 8 def main [ 9 + # TODO: --choose (-c) # Interactively choose a function 9 10 --list (-l) # List avaliable functions 10 11 --interactive (-i) # Enter interactive shell with the module loaded 11 12 ...function 12 13 ] { 13 14 let function = $function | str join ' ' 14 - if $list or ($function | is-empty) { 15 + if $interactive { 16 + exec nu -e "use atomic-xr; print $'(ansi yellow)AtomicXR module loaded.(ansi reset)'" 17 + } else if $list or ($function | is-empty) { 15 18 print-functions 16 - } else if $interactive { 17 - nu -e "use atomic-xr" 18 19 } else { 19 20 # Make sure the function is valid to avoid unhelpful error messages (doesn't check flags) 20 - if ($function | str replace -r " -.*" '') in (get-functions) { 21 + if ($function | str replace -r " -.*" '') in (get-functions | append (get-aliases)) { 21 22 nu -c $"use atomic-xr ; atomic-xr ($function)" 22 23 } else { 23 24 log error $"Invalid function: `($function)`" ··· 30 31 scope modules 31 32 | where name == atomic-xr 32 33 | get 0.commands.name 33 - | where $it != "self install" # This command can only be safely used if the same module version that's loaded is the one being installed, which is never the case with `axr` 34 + } 35 + 36 + def get-aliases [] { 37 + scope modules 38 + | where name == atomic-xr 39 + | get 0.aliases.name 34 40 } 35 41 36 42 def print-functions [] { ··· 46 52 $in 47 53 } 48 54 49 - let usage = $help 50 - | get ( 51 - ($help | enumerate | where item == $"(ansi green)Usage(ansi reset):").0.index + 1 52 - ) 53 - | str trim 55 + # let usage = $help 56 + # | get ( 57 + # ($help | enumerate | where item == $"(ansi green)Usage(ansi reset):").0.index + 1 58 + # ) 59 + # | str trim 54 60 55 - [ 56 - $usage 57 - (if $short_description == null {null} else { 58 - $"(ansi blue)- ($short_description)(ansi reset)" 59 - }) 60 - ] | str join ' ' 61 + { 62 + command: $"(ansi cyan)($function)(ansi reset)" 63 + description: $"(ansi lp)($short_description)(ansi reset)" 64 + } 61 65 } 62 - | prepend "Avaliable functions:" 63 - | append "\n" # Fixes some shell prompts not displaying on a new line 64 - | str join "\n" 66 + | table --index false --theme rounded 65 67 }
-13
src/oscavmgr-launch.sh
··· 1 - #!/usr/bin/env bash 2 - # SPDX-License-Identifier: AGPL-3.0-only 3 - # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 - # 5 - # Portions of this file are derived from OscAvMgr, which is licensed under the MIT License 6 - # Copyright (c) 2023 galister 7 - 8 - 9 - trap 'jobs -p | xargs kill' EXIT 10 - 11 - VrcAdvert OscAvMgr 9402 9002 --tracking & 12 - 13 - oscavmgr "${@}"