├── .editorconfig ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── dependabot.yml ├── labeler.yml └── workflows │ ├── build-gui.yml │ ├── gradle.yaml │ ├── label.yml │ ├── pontoon-pr.yml │ └── rebase.yml ├── .gitignore ├── .gitmodules ├── .husky └── pre-commit ├── .imgbotconfig ├── .lintstagedrc.mjs ├── .node-version ├── .npmrc ├── .prettierrc ├── .vscode └── extensions.json ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── TRADEMARK.md ├── assets └── img │ └── onboarding.png ├── build.gradle.kts ├── deny.toml ├── dev.slimevr.SlimeVR.metainfo.xml ├── flake.lock ├── flake.nix ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── gui ├── .env ├── .gitattributes ├── .gitignore ├── .lintstagedrc.mjs ├── eslint.config.js ├── index.html ├── openapi-codegen.config.ts ├── package.json ├── postcss.config.cjs ├── public │ ├── favicon.ico │ ├── fonts │ │ ├── Lexend[HEXP,wght].woff2 │ │ ├── NotoSansCJK-VF.otf.woff2 │ │ ├── OpenDyslexic-Bold-Italic.woff │ │ ├── OpenDyslexic-Bold.woff │ │ ├── OpenDyslexic-Italic.woff │ │ ├── OpenDyslexic-Regular.woff │ │ └── Ubuntu-R.woff2 │ ├── i18n │ │ ├── ar │ │ │ └── translation.ftl │ │ ├── cs │ │ │ └── translation.ftl │ │ ├── da │ │ │ └── translation.ftl │ │ ├── de │ │ │ └── translation.ftl │ │ ├── el │ │ │ └── translation.ftl │ │ ├── en-x-owo │ │ │ └── translation.ftl │ │ ├── en │ │ │ └── translation.ftl │ │ ├── es-419 │ │ │ └── translation.ftl │ │ ├── es-ES │ │ │ └── translation.ftl │ │ ├── et │ │ │ └── translation.ftl │ │ ├── fi │ │ │ └── translation.ftl │ │ ├── fr │ │ │ └── translation.ftl │ │ ├── he │ │ │ └── translation.ftl │ │ ├── it │ │ │ └── translation.ftl │ │ ├── ja │ │ │ └── translation.ftl │ │ ├── ko │ │ │ └── translation.ftl │ │ ├── nb-NO │ │ │ └── translation.ftl │ │ ├── nl │ │ │ └── translation.ftl │ │ ├── pl │ │ │ └── translation.ftl │ │ ├── pt-BR │ │ │ └── translation.ftl │ │ ├── ru │ │ │ └── translation.ftl │ │ ├── th │ │ │ └── translation.ftl │ │ ├── tr │ │ │ └── translation.ftl │ │ ├── uk │ │ │ └── translation.ftl │ │ ├── vi │ │ │ └── translation.ftl │ │ ├── zh-Hans │ │ │ └── translation.ftl │ │ └── zh-Hant │ │ │ └── translation.ftl │ ├── images │ │ ├── R11_board_reset.webp │ │ ├── R12_board_reset.webp │ │ ├── R14_board_reset_sw.webp │ │ ├── autobone-poster.webp │ │ ├── boxslime.webp │ │ ├── curious-slime.gif │ │ ├── front-standing-pose.webp │ │ ├── happy-slime.gif │ │ ├── jumping-slime.gif │ │ ├── mounting-reset-pose.webp │ │ ├── relaxed_pose_flat.webp │ │ ├── relaxed_pose_sitting.webp │ │ ├── relaxed_pose_standing.webp │ │ ├── reset-pose.webp │ │ ├── reset │ │ │ ├── FullResetPose.webp │ │ │ ├── FullResetPoseSide.webp │ │ │ └── FullResetPoseWrong.webp │ │ ├── sad-slime.gif │ │ ├── slime-girl.webp │ │ ├── slimes.webp │ │ ├── slimetower.webp │ │ └── stay-aligned │ │ │ ├── StayAlignedFloor.webp │ │ │ ├── StayAlignedSitting.webp │ │ │ └── StayAlignedStanding.webp │ ├── logo.svg │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── models │ │ ├── extension.gltf │ │ └── tracker.gltf │ ├── robots.txt │ └── videos │ │ ├── autobone.webm │ │ └── turn-on-tracker.webm ├── scripts │ ├── check-missing.js │ ├── convert-fluent.js │ ├── gitversion.mjs │ └── license-list.mjs ├── src-tauri │ ├── .gitignore │ ├── .lintstagedrc.mjs │ ├── Cargo.toml │ ├── build.rs │ ├── capabilities │ │ └── migrated.json │ ├── dev.slimevr.SlimeVR.desktop │ ├── icons │ │ ├── 128x128.png │ │ ├── 128x128@2x.png │ │ ├── 32x32.png │ │ ├── Square107x107Logo.png │ │ ├── Square142x142Logo.png │ │ ├── Square150x150Logo.png │ │ ├── Square284x284Logo.png │ │ ├── Square30x30Logo.png │ │ ├── Square310x310Logo.png │ │ ├── Square44x44Logo.png │ │ ├── Square71x71Logo.png │ │ ├── Square89x89Logo.png │ │ ├── StoreLogo.png │ │ ├── android │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ └── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ ├── appleTrayIcon.png │ │ ├── icon.icns │ │ ├── icon.ico │ │ ├── icon.png │ │ ├── icon.svg │ │ └── ios │ │ │ ├── AppIcon-20x20@1x.png │ │ │ ├── AppIcon-20x20@2x-1.png │ │ │ ├── AppIcon-20x20@2x.png │ │ │ ├── AppIcon-20x20@3x.png │ │ │ ├── AppIcon-29x29@1x.png │ │ │ ├── AppIcon-29x29@2x-1.png │ │ │ ├── AppIcon-29x29@2x.png │ │ │ ├── AppIcon-29x29@3x.png │ │ │ ├── AppIcon-40x40@1x.png │ │ │ ├── AppIcon-40x40@2x-1.png │ │ │ ├── AppIcon-40x40@2x.png │ │ │ ├── AppIcon-40x40@3x.png │ │ │ ├── AppIcon-512@2x.png │ │ │ ├── AppIcon-60x60@2x.png │ │ │ ├── AppIcon-60x60@3x.png │ │ │ ├── AppIcon-76x76@1x.png │ │ │ ├── AppIcon-76x76@2x.png │ │ │ └── AppIcon-83.5x83.5@2x.png │ ├── run.bat.old │ ├── src │ │ ├── JavaVersion.jar │ │ ├── JavaVersion.java │ │ ├── main.rs │ │ ├── presence.rs │ │ ├── state.rs │ │ ├── tray.rs │ │ └── util.rs │ └── tauri.conf.json ├── src │ ├── App.tsx │ ├── AppLayout.tsx │ ├── components │ │ ├── BVHButton.tsx │ │ ├── ClearMountingButton.tsx │ │ ├── EmptyLayout.scss │ │ ├── EmptyLayout.tsx │ │ ├── ErrorConsentModal.tsx │ │ ├── MainLayout.scss │ │ ├── MainLayout.tsx │ │ ├── Navbar.tsx │ │ ├── Preload.tsx │ │ ├── SerialDetectionModal.tsx │ │ ├── TopBar.tsx │ │ ├── TrackersStillOnModal.tsx │ │ ├── TrackingPauseButton.tsx │ │ ├── TrayOrExitModal.tsx │ │ ├── UnknownDeviceModal.tsx │ │ ├── VersionUpdateModal.tsx │ │ ├── WidgetsComponent.tsx │ │ ├── commons │ │ │ ├── A.tsx │ │ │ ├── ArrowLink.tsx │ │ │ ├── BaseModal.tsx │ │ │ ├── BigButton.tsx │ │ │ ├── BodyDisplay.tsx │ │ │ ├── BodyInteractions.tsx │ │ │ ├── BodyPartIcon.tsx │ │ │ ├── Button.tsx │ │ │ ├── Checkbox.tsx │ │ │ ├── Dropdown.tsx │ │ │ ├── FileInput.tsx │ │ │ ├── Input.tsx │ │ │ ├── LangSelector.tsx │ │ │ ├── Modal.tsx │ │ │ ├── NumberSelector.tsx │ │ │ ├── PersonFrontIcon.tsx │ │ │ ├── ProgressBar.tsx │ │ │ ├── Radio.tsx │ │ │ ├── Range.tsx │ │ │ ├── ThemeSelector.tsx │ │ │ ├── TipBox.tsx │ │ │ ├── Tooltip.tsx │ │ │ ├── Typography.tsx │ │ │ ├── VerticalStepper.tsx │ │ │ └── icon │ │ │ │ ├── AnkleIcon.tsx │ │ │ │ ├── ArrowIcons.tsx │ │ │ │ ├── BatteryIcon.tsx │ │ │ │ ├── BellIcon.tsx │ │ │ │ ├── BugIcon.tsx │ │ │ │ ├── BulbIcon.tsx │ │ │ │ ├── CheckIcon.tsx │ │ │ │ ├── ChestIcon.tsx │ │ │ │ ├── CircleIcon.tsx │ │ │ │ ├── CloseIcon.tsx │ │ │ │ ├── ControllerIcon.tsx │ │ │ │ ├── CrossIcon.tsx │ │ │ │ ├── CubeIcon.tsx │ │ │ │ ├── DownloadIcon.tsx │ │ │ │ ├── EscapeIcon.tsx │ │ │ │ ├── EyeIcon.tsx │ │ │ │ ├── FileIcon.tsx │ │ │ │ ├── FingersIcon.tsx │ │ │ │ ├── FootIcon.tsx │ │ │ │ ├── FrontOfChair.tsx │ │ │ │ ├── GearIcon.tsx │ │ │ │ ├── HeadIcon.tsx │ │ │ │ ├── HeadsetIcon.tsx │ │ │ │ ├── HipIcon.tsx │ │ │ │ ├── HumanIcon.tsx │ │ │ │ ├── ImportIcon.tsx │ │ │ │ ├── LoaderIcon.tsx │ │ │ │ ├── LowerArmIcon.tsx │ │ │ │ ├── MaximiseIcon.tsx │ │ │ │ ├── MinimiseIcon.tsx │ │ │ │ ├── NeckIcon.tsx │ │ │ │ ├── PauseIcon.tsx │ │ │ │ ├── PawIcon.tsx │ │ │ │ ├── PercentIcon.tsx │ │ │ │ ├── PlayIcon.tsx │ │ │ │ ├── QuestionIcon.tsx │ │ │ │ ├── RecordIcon.tsx │ │ │ │ ├── ResetIcon.tsx │ │ │ │ ├── RouterIcon.tsx │ │ │ │ ├── RulerIcon.tsx │ │ │ │ ├── ShoulderIcon.tsx │ │ │ │ ├── SimevrIcon.tsx │ │ │ │ ├── SlimeUpIcon.tsx │ │ │ │ ├── SlimeVRIcon.tsx │ │ │ │ ├── SparkleIcon.tsx │ │ │ │ ├── SpinIcon.tsx │ │ │ │ ├── SquaresIcon.tsx │ │ │ │ ├── SteamIcon.tsx │ │ │ │ ├── TaybolIcon.tsx │ │ │ │ ├── TrashIcon.tsx │ │ │ │ ├── UploadFileIcon.tsx │ │ │ │ ├── UpperArmIcon.tsx │ │ │ │ ├── UpperChestIcon.tsx │ │ │ │ ├── UpperLegIcon.tsx │ │ │ │ ├── UsbIcon.tsx │ │ │ │ ├── VMCIcon.tsx │ │ │ │ ├── VRCIcon.tsx │ │ │ │ ├── WaistIcon.tsx │ │ │ │ ├── WarningIcon.tsx │ │ │ │ ├── WifiIcon.tsx │ │ │ │ └── WrenchIcons.tsx │ │ ├── firmware-tool │ │ │ ├── AddImusStep.tsx │ │ │ ├── BoardPinsStep.tsx │ │ │ ├── BuildStep.tsx │ │ │ ├── DeviceCard.tsx │ │ │ ├── FirmwareTool.tsx │ │ │ ├── FlashBtnStep.tsx │ │ │ ├── FlashingMethodStep.tsx │ │ │ ├── FlashingStep.tsx │ │ │ ├── SelectBoardStep.tsx │ │ │ └── SelectFirmwareStep.tsx │ │ ├── firmware-update │ │ │ └── FirmwareUpdate.tsx │ │ ├── home │ │ │ ├── Home.tsx │ │ │ └── ResetButton.tsx │ │ ├── onboarding │ │ │ ├── BodyAssignment.tsx │ │ │ ├── NeckWarningModal.tsx │ │ │ ├── OnboardingContextProvicer.tsx │ │ │ ├── OnboardingLayout.scss │ │ │ ├── OnboardingLayout.tsx │ │ │ ├── SkipSetupButton.tsx │ │ │ ├── SkipSetupWarningModal.tsx │ │ │ ├── StepperSlider.tsx │ │ │ └── pages │ │ │ │ ├── CalibrationTutorial.tsx │ │ │ │ ├── ConnectTracker.scss │ │ │ │ ├── ConnectTracker.tsx │ │ │ │ ├── ConnectionLost.tsx │ │ │ │ ├── Done.tsx │ │ │ │ ├── EnterVR.tsx │ │ │ │ ├── Home.tsx │ │ │ │ ├── ResetTutorial.tsx │ │ │ │ ├── WifiCreds.tsx │ │ │ │ ├── assignment-preparation │ │ │ │ ├── AssignmentTutorial.tsx │ │ │ │ ├── ExtensionArrow.tsx │ │ │ │ ├── StickerSlime.tsx │ │ │ │ └── TrackerArrow.tsx │ │ │ │ ├── body-proportions │ │ │ │ ├── AutomaticProportions.tsx │ │ │ │ ├── BodyProportions.tsx │ │ │ │ ├── ManualProportions.tsx │ │ │ │ ├── ProportionsResetModal.tsx │ │ │ │ ├── ScaledProportions.tsx │ │ │ │ ├── autobone-steps │ │ │ │ │ ├── AutoboneErrorModal.tsx │ │ │ │ │ ├── CheckFloorHeight.tsx │ │ │ │ │ ├── CheckHeight.tsx │ │ │ │ │ ├── Done.tsx │ │ │ │ │ ├── Preparation.tsx │ │ │ │ │ ├── PutTrackersOn.tsx │ │ │ │ │ ├── Recording.tsx │ │ │ │ │ ├── Requirements.tsx │ │ │ │ │ ├── StartRecording.tsx │ │ │ │ │ ├── TooSmolModal.tsx │ │ │ │ │ └── VerifyResults.tsx │ │ │ │ └── scaled-steps │ │ │ │ │ ├── Done.tsx │ │ │ │ │ ├── ManualHeightStep.tsx │ │ │ │ │ └── ResetProportions.tsx │ │ │ │ ├── mounting │ │ │ │ ├── AutomaticMounting.tsx │ │ │ │ ├── ManualMounting.tsx │ │ │ │ ├── MountingChoose.tsx │ │ │ │ ├── MountingSelectionMenu.tsx │ │ │ │ └── mounting-steps │ │ │ │ │ ├── Done.tsx │ │ │ │ │ ├── MountingReset.tsx │ │ │ │ │ ├── Preparation.tsx │ │ │ │ │ └── PutTrackersOn.tsx │ │ │ │ ├── stay-aligned │ │ │ │ ├── StayAlignedSetup.tsx │ │ │ │ └── stay-aligned-steps │ │ │ │ │ ├── Done.tsx │ │ │ │ │ ├── PreparationStep.tsx │ │ │ │ │ ├── PutTrackersOnStep.tsx │ │ │ │ │ ├── RelaxedPoseSteps.tsx │ │ │ │ │ └── VerifyMounting.tsx │ │ │ │ └── trackers-assign │ │ │ │ ├── TrackerAssignOptions.tsx │ │ │ │ ├── TrackerAssignment.tsx │ │ │ │ └── TrackerSelectionMenu.tsx │ │ ├── providers │ │ │ ├── AppContext.tsx │ │ │ ├── ConfigContext.tsx │ │ │ └── StatusSystemContext.tsx │ │ ├── settings │ │ │ ├── HandsWarningModal.tsx │ │ │ ├── SettingsLayout.scss │ │ │ ├── SettingsLayout.tsx │ │ │ ├── SettingsPageLayout.tsx │ │ │ ├── SettingsResetModal.tsx │ │ │ ├── SettingsSidebar.tsx │ │ │ └── pages │ │ │ │ ├── AdvancedSettings.tsx │ │ │ │ ├── GeneralSettings.tsx │ │ │ │ ├── InterfaceSettings.tsx │ │ │ │ ├── MagnetometerToggleSetting.tsx │ │ │ │ ├── OSCRouterSettings.tsx │ │ │ │ ├── Serial.tsx │ │ │ │ ├── VMCSettings.tsx │ │ │ │ ├── VRCOSCSettings.tsx │ │ │ │ └── components │ │ │ │ └── StayAlignedSettings.tsx │ │ ├── stay-aligned │ │ │ ├── RelaxedPose.tsx │ │ │ └── StayAlignedInfo.tsx │ │ ├── tracker │ │ │ ├── SingleTrackerBodyAssignmentMenu.tsx │ │ │ ├── TrackerBattery.tsx │ │ │ ├── TrackerCard.tsx │ │ │ ├── TrackerPartCard.tsx │ │ │ ├── TrackerSettings.tsx │ │ │ ├── TrackerStatus.tsx │ │ │ ├── TrackerWifi.tsx │ │ │ └── TrackersTable.tsx │ │ ├── vr-mode │ │ │ └── VRModePage.tsx │ │ ├── vrc │ │ │ └── VRCWarningsPage.tsx │ │ └── widgets │ │ │ ├── DeveloperModeWidget.tsx │ │ │ ├── IMUVisualizerWidget.tsx │ │ │ ├── OverlayWidget.tsx │ │ │ └── SkeletonVisualizerWidget.tsx │ ├── firmware-tool-api │ │ ├── firmwareToolComponents.ts │ │ ├── firmwareToolContext.ts │ │ ├── firmwareToolFetcher.ts │ │ ├── firmwareToolSchemas.ts │ │ └── firmwareToolUtils.ts │ ├── hooks │ │ ├── app.ts │ │ ├── autobone.ts │ │ ├── breakpoint.ts │ │ ├── cache.ts │ │ ├── choker-warning.ts │ │ ├── config.ts │ │ ├── countdown.ts │ │ ├── datafeed-config.ts │ │ ├── discord-presence.ts │ │ ├── firmware-tool.ts │ │ ├── height.ts │ │ ├── imu-logic.ts │ │ ├── layout.ts │ │ ├── manual-proportions.ts │ │ ├── onboarding.ts │ │ ├── previous.ts │ │ ├── pubSub.ts │ │ ├── status-system.ts │ │ ├── timeout.ts │ │ ├── tracker.ts │ │ ├── vrc-config.ts │ │ ├── websocket-api.ts │ │ └── wifi-form.tsx │ ├── i18n │ │ ├── config.tsx │ │ └── names.ts │ ├── index.scss │ ├── index.tsx │ ├── logo.svg │ ├── maths │ │ ├── angle.ts │ │ ├── quaternion.ts │ │ └── vector3.ts │ ├── setupTests.ts │ ├── sounds │ │ ├── sounds.ts │ │ └── xylophone.ts │ ├── store │ │ └── app-store.ts │ ├── utils │ │ ├── a11y.ts │ │ ├── formatting.ts │ │ ├── logging.ts │ │ ├── sentry.ts │ │ ├── skeletonHelper.ts │ │ └── tauri.ts │ └── vite-env.d.ts ├── tailwind.config.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── l10n.toml ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── rust-toolchain.toml ├── rustfmt.toml ├── server ├── .gitattributes ├── .gitignore ├── LICENSE.md ├── android │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-playstore.png │ │ ├── java │ │ ├── dev │ │ │ └── slimevr │ │ │ │ └── android │ │ │ │ ├── ForegroundService.kt │ │ │ │ ├── Main.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ └── serial │ │ │ │ └── AndroidSerialHandler.kt │ │ └── java │ │ │ └── awt │ │ │ └── Color.java │ │ ├── res │ │ ├── drawable │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout │ │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ │ └── themes.xml │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ └── xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ │ └── resources │ │ ├── icon128.png │ │ ├── icon16.png │ │ ├── icon256.png │ │ ├── icon32.png │ │ ├── icon48.png │ │ └── icon64.png ├── build.gradle.kts ├── core │ ├── .gitignore │ ├── build.gradle.kts │ ├── protobuf_update.bat │ ├── resources │ │ ├── ThirdPartyNotices.txt │ │ ├── firewall.bat │ │ └── firewall_uninstall.bat │ └── src │ │ ├── main │ │ └── java │ │ │ ├── com │ │ │ └── jme3 │ │ │ │ ├── math │ │ │ │ └── FastMath.kt │ │ │ │ └── system │ │ │ │ ├── NanoTimer.java │ │ │ │ └── Timer.java │ │ │ ├── dev │ │ │ └── slimevr │ │ │ │ ├── Keybinding.kt │ │ │ │ ├── NetworkProtocol.java │ │ │ │ ├── VRServer.kt │ │ │ │ ├── autobone │ │ │ │ ├── AutoBone.kt │ │ │ │ ├── AutoBoneHandler.kt │ │ │ │ ├── AutoBoneListener.kt │ │ │ │ ├── AutoBoneProcessType.kt │ │ │ │ ├── AutoBoneStep.kt │ │ │ │ ├── BoneContribution.kt │ │ │ │ ├── PoseFrameIterator.kt │ │ │ │ ├── PoseFrameStep.kt │ │ │ │ ├── StatsCalculator.kt │ │ │ │ └── errors │ │ │ │ │ ├── AutoBoneException.kt │ │ │ │ │ ├── BodyProportionError.kt │ │ │ │ │ ├── FootHeightOffsetError.kt │ │ │ │ │ ├── HeightError.kt │ │ │ │ │ ├── IAutoBoneError.kt │ │ │ │ │ ├── OffsetSlideError.kt │ │ │ │ │ ├── PositionError.kt │ │ │ │ │ ├── PositionOffsetError.kt │ │ │ │ │ ├── SlideError.kt │ │ │ │ │ └── proportions │ │ │ │ │ ├── HardProportionLimiter.kt │ │ │ │ │ ├── ProportionLimiter.kt │ │ │ │ │ └── RangeProportionLimiter.kt │ │ │ │ ├── bridge │ │ │ │ ├── Bridge.kt │ │ │ │ └── BridgeThread.java │ │ │ │ ├── config │ │ │ │ ├── AutoBoneConfig.kt │ │ │ │ ├── BridgeConfig.java │ │ │ │ ├── ConfigManager.java │ │ │ │ ├── CurrentVRConfigConverter.java │ │ │ │ ├── DriftCompensationConfig.kt │ │ │ │ ├── FiltersConfig.kt │ │ │ │ ├── KeybindingsConfig.java │ │ │ │ ├── LegTweaksConfig.kt │ │ │ │ ├── OSCConfig.kt │ │ │ │ ├── OverlayConfig.java │ │ │ │ ├── ResetsConfig.kt │ │ │ │ ├── ServerConfig.kt │ │ │ │ ├── SkeletonConfig.java │ │ │ │ ├── StayAlignedConfig.kt │ │ │ │ ├── StayAlignedRelaxedPoseConfig.kt │ │ │ │ ├── TapDetectionConfig.kt │ │ │ │ ├── TrackerConfig.kt │ │ │ │ ├── VMCConfig.kt │ │ │ │ ├── VRCOSCConfig.kt │ │ │ │ ├── VRConfig.kt │ │ │ │ └── serializers │ │ │ │ │ ├── BooleanMapDeserializer.java │ │ │ │ │ ├── BridgeConfigMapDeserializer.java │ │ │ │ │ ├── FloatMapDeserializer.java │ │ │ │ │ ├── MapDeserializer.java │ │ │ │ │ ├── QuaternionDeserializer.java │ │ │ │ │ ├── QuaternionSerializer.java │ │ │ │ │ └── TrackerConfigMapDeserializer.java │ │ │ │ ├── filtering │ │ │ │ ├── CircularArrayList.java │ │ │ │ ├── QuaternionMovingAverage.kt │ │ │ │ └── TrackerFilters.kt │ │ │ │ ├── firmware │ │ │ │ ├── FirmwareUpdateHandler.kt │ │ │ │ ├── FirmwareUpdateListener.kt │ │ │ │ ├── FirmwareUpdateMethod.kt │ │ │ │ ├── FirmwareUpdateStatus.kt │ │ │ │ ├── OTAUpdateTask.kt │ │ │ │ ├── SerialFlashingHandler.kt │ │ │ │ ├── SerialRebootHandler.kt │ │ │ │ ├── UpdateDeviceId.kt │ │ │ │ └── UpdateStatusEvent.kt │ │ │ │ ├── games │ │ │ │ └── vrchat │ │ │ │ │ └── VRCConfigHandler.kt │ │ │ │ ├── math │ │ │ │ ├── Angle.kt │ │ │ │ ├── AngleAverage.kt │ │ │ │ └── AngleErrors.kt │ │ │ │ ├── osc │ │ │ │ ├── OSCHandler.java │ │ │ │ ├── OSCRouter.java │ │ │ │ ├── UnityArmature.kt │ │ │ │ ├── UnityBone.kt │ │ │ │ ├── VMCHandler.kt │ │ │ │ ├── VRCOSCHandler.kt │ │ │ │ ├── VRCOSCQueryHandler.kt │ │ │ │ └── VRMReader.kt │ │ │ │ ├── poseframeformat │ │ │ │ ├── PfrIO.kt │ │ │ │ ├── PfsIO.kt │ │ │ │ ├── PfsPackets.kt │ │ │ │ ├── PoseFrames.kt │ │ │ │ ├── PoseRecorder.kt │ │ │ │ ├── player │ │ │ │ │ ├── PlayerTracker.kt │ │ │ │ │ └── TrackerFramesPlayer.kt │ │ │ │ └── trackerdata │ │ │ │ │ ├── TrackerFrame.kt │ │ │ │ │ ├── TrackerFrameData.kt │ │ │ │ │ └── TrackerFrames.kt │ │ │ │ ├── posestreamer │ │ │ │ ├── BVHFileStream.kt │ │ │ │ ├── BVHRecorder.java │ │ │ │ ├── BVHSettings.java │ │ │ │ ├── PoseDataStream.java │ │ │ │ ├── PoseFrameStreamer.kt │ │ │ │ ├── PoseStreamer.java │ │ │ │ ├── ServerPoseStreamer.java │ │ │ │ └── TickPoseStreamer.java │ │ │ │ ├── protocol │ │ │ │ ├── ConnectionContext.java │ │ │ │ ├── GenericConnection.java │ │ │ │ ├── ProtocolAPI.java │ │ │ │ ├── ProtocolAPIServer.java │ │ │ │ ├── ProtocolHandler.kt │ │ │ │ ├── datafeed │ │ │ │ │ ├── DataFeedBuilder.java │ │ │ │ │ ├── DataFeedBuilderKotlin.kt │ │ │ │ │ └── DataFeedHandler.java │ │ │ │ ├── pubsub │ │ │ │ │ ├── HashedTopicId.java │ │ │ │ │ └── PubSubHandler.java │ │ │ │ └── rpc │ │ │ │ │ ├── RPCBuilder.java │ │ │ │ │ ├── RPCBuilder.kt │ │ │ │ │ ├── RPCHandler.kt │ │ │ │ │ ├── autobone │ │ │ │ │ └── RPCAutoBoneHandler.kt │ │ │ │ │ ├── firmware │ │ │ │ │ └── RPCFirmwareUpdateHandler.kt │ │ │ │ │ ├── games │ │ │ │ │ └── vrchat │ │ │ │ │ │ ├── RPCVRCBuilder.kt │ │ │ │ │ │ └── RPCVRChatHandler.kt │ │ │ │ │ ├── reset │ │ │ │ │ └── RPCResetHandler.java │ │ │ │ │ ├── serial │ │ │ │ │ ├── RPCProvisioningHandler.java │ │ │ │ │ └── RPCSerialHandler.java │ │ │ │ │ ├── settings │ │ │ │ │ ├── RPCSettingsBuilder.java │ │ │ │ │ ├── RPCSettingsBuilderKotlin.kt │ │ │ │ │ └── RPCSettingsHandler.kt │ │ │ │ │ ├── setup │ │ │ │ │ ├── RPCHandshakeHandler.kt │ │ │ │ │ ├── RPCTapSetupHandler.kt │ │ │ │ │ └── RPCUtil.kt │ │ │ │ │ ├── status │ │ │ │ │ └── RPCStatusHandler.kt │ │ │ │ │ └── trackingpause │ │ │ │ │ └── RPCTrackingPause.kt │ │ │ │ ├── reset │ │ │ │ ├── ResetHandler.java │ │ │ │ └── ResetListener.java │ │ │ │ ├── serial │ │ │ │ ├── ProvisioningHandler.java │ │ │ │ ├── ProvisioningListener.java │ │ │ │ ├── ProvisioningStatus.kt │ │ │ │ ├── SerialHandler.kt │ │ │ │ └── SerialListener.kt │ │ │ │ ├── setup │ │ │ │ ├── HandshakeHandler.kt │ │ │ │ └── TapSetupHandler.kt │ │ │ │ ├── status │ │ │ │ └── StatusSystem.kt │ │ │ │ ├── tracking │ │ │ │ ├── processor │ │ │ │ │ ├── Bone.kt │ │ │ │ │ ├── BoneType.java │ │ │ │ │ ├── Constraint.kt │ │ │ │ │ ├── HumanPoseManager.kt │ │ │ │ │ ├── TransformNode.kt │ │ │ │ │ ├── config │ │ │ │ │ │ ├── SkeletonConfigManager.kt │ │ │ │ │ │ ├── SkeletonConfigOffsets.java │ │ │ │ │ │ ├── SkeletonConfigToggles.java │ │ │ │ │ │ └── SkeletonConfigValues.java │ │ │ │ │ ├── skeleton │ │ │ │ │ │ ├── HumanSkeleton.kt │ │ │ │ │ │ ├── LegTweaks.kt │ │ │ │ │ │ ├── LegTweaksBuffer.kt │ │ │ │ │ │ ├── Localizer.kt │ │ │ │ │ │ ├── TapDetection.kt │ │ │ │ │ │ └── TapDetectionManager.java │ │ │ │ │ └── stayaligned │ │ │ │ │ │ ├── StayAligned.kt │ │ │ │ │ │ ├── StayAlignedDefaults.kt │ │ │ │ │ │ ├── adjust │ │ │ │ │ │ ├── AdjustTrackerYaw.kt │ │ │ │ │ │ ├── CenterErrorVisitor.kt │ │ │ │ │ │ ├── CenterYaw.kt │ │ │ │ │ │ ├── LockedErrorVisitor.kt │ │ │ │ │ │ ├── NeighborErrorVisitor.kt │ │ │ │ │ │ └── TrackerYaw.kt │ │ │ │ │ │ ├── poses │ │ │ │ │ │ ├── PlayerPose.kt │ │ │ │ │ │ ├── RelaxedPose.kt │ │ │ │ │ │ └── TrackerPose.kt │ │ │ │ │ │ └── trackers │ │ │ │ │ │ ├── RestDetector.kt │ │ │ │ │ │ ├── Side.kt │ │ │ │ │ │ ├── StayAlignedTrackerState.kt │ │ │ │ │ │ ├── TrackerSkeleton.kt │ │ │ │ │ │ └── YawErrors.kt │ │ │ │ └── trackers │ │ │ │ │ ├── Device.kt │ │ │ │ │ ├── DeviceManager.kt │ │ │ │ │ ├── Tracker.kt │ │ │ │ │ ├── TrackerFilteringHandler.kt │ │ │ │ │ ├── TrackerFlexHandler.kt │ │ │ │ │ ├── TrackerPosition.kt │ │ │ │ │ ├── TrackerResetsHandler.kt │ │ │ │ │ ├── TrackerRole.kt │ │ │ │ │ ├── TrackerStatus.kt │ │ │ │ │ ├── TrackerStatusListener.kt │ │ │ │ │ ├── TrackerUtils.kt │ │ │ │ │ └── udp │ │ │ │ │ ├── FeatureFlags.kt │ │ │ │ │ ├── FirmwareConstants.kt │ │ │ │ │ ├── SensorTap.kt │ │ │ │ │ ├── TrackersUDPServer.kt │ │ │ │ │ ├── UDPDevice.kt │ │ │ │ │ ├── UDPPacket.kt │ │ │ │ │ └── UDPProtocolParser.kt │ │ │ │ ├── trackingpause │ │ │ │ ├── TrackingPauseHandler.kt │ │ │ │ └── TrackingPauseListener.kt │ │ │ │ ├── util │ │ │ │ └── ann │ │ │ │ │ └── VRServerThread.java │ │ │ │ └── websocketapi │ │ │ │ ├── WebSocketVRBridge.kt │ │ │ │ ├── WebsocketAPI.java │ │ │ │ └── WebsocketConnection.java │ │ │ └── io │ │ │ ├── eiren │ │ │ ├── math │ │ │ │ └── FloatMath.kt │ │ │ └── util │ │ │ │ ├── BufferedTimer.java │ │ │ │ ├── OperatingSystem.kt │ │ │ │ ├── StringUtils.java │ │ │ │ ├── Util.java │ │ │ │ ├── ann │ │ │ │ ├── AWTThread.java │ │ │ │ ├── DebugSwitch.java │ │ │ │ ├── NativeUnsafe.java │ │ │ │ ├── Synchronize.java │ │ │ │ ├── ThreadSafe.java │ │ │ │ ├── ThreadSafeSingle.java │ │ │ │ ├── ThreadSecure.java │ │ │ │ └── Transient.java │ │ │ │ ├── collections │ │ │ │ ├── FastList.java │ │ │ │ ├── RemoveAtSwapFastList.java │ │ │ │ ├── RemoveAtSwapList.java │ │ │ │ ├── ResettableIterator.java │ │ │ │ └── SkipIterator.java │ │ │ │ └── logging │ │ │ │ ├── DefaultGLog.java │ │ │ │ ├── FileLogFormatter.java │ │ │ │ ├── FileLogHandler.kt │ │ │ │ ├── IGLog.java │ │ │ │ ├── LogManager.java │ │ │ │ ├── LoggerOutputStream.java │ │ │ │ ├── LoggerRecorder.java │ │ │ │ ├── PreciseConsoleLogFormatter.java │ │ │ │ └── ShortConsoleLogFormatter.java │ │ │ └── github │ │ │ └── axisangles │ │ │ └── ktmath │ │ │ ├── EulerAngles.kt │ │ │ ├── LICENSE-APACHE │ │ │ ├── LICENSE-MIT │ │ │ ├── Matrix3.kt │ │ │ ├── Quaternion.kt │ │ │ ├── Transform.kt │ │ │ └── Vector3.kt │ │ └── test │ │ └── java │ │ ├── dev │ │ └── slimevr │ │ │ └── unit │ │ │ ├── LegTweaksTests.kt │ │ │ ├── MountingResetTests.kt │ │ │ ├── ReferenceAdjustmentsTests.kt │ │ │ ├── SkeletonResetTests.kt │ │ │ ├── TestTrackerSet.kt │ │ │ ├── TrackerTestUtils.kt │ │ │ ├── TrackingPauseTests.kt │ │ │ └── TwinExtendedBackTests.kt │ │ └── io │ │ └── github │ │ └── axisangles │ │ └── ktmath │ │ └── QuaternionTest.kt ├── desktop │ ├── .gitignore │ ├── build.gradle.kts │ ├── config │ │ └── README.md │ └── src │ │ └── main │ │ └── java │ │ └── dev │ │ └── slimevr │ │ └── desktop │ │ ├── Main.kt │ │ ├── NetworkProfileChecker.kt │ │ ├── firmware │ │ └── DesktopSerialFlashingHandler.kt │ │ ├── games │ │ └── vrchat │ │ │ └── DesktopVRCConfigHandler.kt │ │ ├── platform │ │ ├── ProtobufBridge.kt │ │ ├── ProtobufMessages.java │ │ ├── SteamVRBridge.kt │ │ ├── linux │ │ │ ├── UnixSocketBridge.java │ │ │ ├── UnixSocketConnection.java │ │ │ └── UnixSocketRpcBridge.java │ │ └── windows │ │ │ ├── PipeState.java │ │ │ ├── WindowsNamedPipeBridge.java │ │ │ └── WindowsPipe.java │ │ ├── serial │ │ └── DesktopSerialHandler.kt │ │ └── tracking │ │ └── trackers │ │ └── hid │ │ ├── HIDDevice.kt │ │ └── TrackersHID.kt └── spotless.xml ├── settings.gradle.kts └── shell.nix /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | charset = utf-8 7 | 8 | # Fluent files only support spaces for indentation 9 | [*.ftl] 10 | indent_size = 4 11 | indent_style = space 12 | 13 | # Current config in eslint uses 2 spaces for indentation 14 | [*.{.tsx,ts,jsx,js}] 15 | indent_size = 2 16 | indent_style = space 17 | max_line_length = 88 18 | 19 | # This is how everything should actually be 20 | [*.{kt,kts,java,rs}] 21 | indent_size = 4 22 | indent_style = tab 23 | max_line_length = 88 24 | ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlin.math.* 25 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" 3 | fi 4 | 5 | nix_direnv_watch_file rust-toolchain.toml 6 | nix_direnv_watch_file package.json 7 | if ! use flake . --impure 8 | then 9 | echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 10 | fi 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.png binary 4 | *.webp binary 5 | *.gif binary 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Global code owner 2 | * @Eirenliel 3 | 4 | # Make everyone be able to approve SolarXR submodule changes 5 | /solarxr-protocol @ButterscotchV @Erimelowo @ImUrX @loucass003 6 | 7 | # Make Loucas and Uriel the owners of all GUI stuff 8 | /gui/ @ImUrX @loucass003 9 | /pnpm-lock.yaml @ImUrX @loucass003 10 | /pnpm-workspace.yaml @ImUrX @loucass003 11 | 12 | # Uriel and Erimel responsible for i18n 13 | /gui/public/i18n/ @ImUrX @Erimelowo 14 | /gui/src/i18n/ @ImUrX @Erimelowo 15 | /l10n.toml @ImUrX @Erimelowo 16 | 17 | /gui/src/components/settings/ @Erimelowo @ImUrX 18 | 19 | # Rust part of the GUI 20 | /gui/src-tauri/ @ImUrX 21 | /Cargo.lock @ImUrX 22 | 23 | # Some server code~ 24 | /server/ @ButterscotchV @Eirenliel @Erimelowo 25 | 26 | /server/src/main/java/dev/slimevr/autobone/ @ButterscotchV 27 | /server/src/main/java/dev/slimevr/poserecorder/ @ButterscotchV 28 | /server/src/main/java/dev/slimevr/posestreamer/ @ButterscotchV 29 | 30 | /server/src/main/java/dev/slimevr/osc/ @Erimelowo 31 | /server/src/main/java/dev/slimevr/tracking/processor/ @Erimelowo 32 | /server/src/main/java/dev/slimevr/filtering/ @Erimelowo 33 | 34 | # Linux files 35 | *.nix @ImUrX 36 | /flake.lock @ImUrX 37 | /dev.slimevr.SlimeVR.metainfo.xml @ImUrX 38 | /.envrc @ImUrX 39 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: SlimeVR 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | # Check for updates to GitHub Actions every week 8 | interval: "weekly" 9 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | # This workflow will triage pull requests and apply a label based on the 2 | # paths that are modified in the pull request. 3 | # 4 | # To use this workflow, you will need to set up a .github/labeler.yml 5 | # file with configuration. For more information, see: 6 | # https://github.com/actions/labeler 7 | 8 | name: Labeler 9 | on: [pull_request_target] 10 | 11 | jobs: 12 | label: 13 | 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: read 17 | pull-requests: write 18 | 19 | steps: 20 | - uses: actions/labeler@v5 21 | with: 22 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 23 | -------------------------------------------------------------------------------- /.github/workflows/pontoon-pr.yml: -------------------------------------------------------------------------------- 1 | name: Update translations in main 2 | on: 3 | push: 4 | branches: 5 | - pontoon 6 | 7 | jobs: 8 | pull_request: 9 | if: ${{ github.repository == 'SlimeVR/SlimeVR-Server' }} 10 | runs-on: ubuntu-latest 11 | permissions: 12 | pull-requests: write 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | submodules: recursive 18 | - uses: repo-sync/pull-request@v2 19 | with: 20 | destination_branch: "main" 21 | pr_title: "New Pontoon translations" 22 | pr_body: "Please don't squash me 🥺" 23 | pr_label: "Area: Translation" 24 | github_token: ${{ secrets.PONTOON_BOT_KEY }} 25 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | # This workflow will rebase `pontoon` with `main` changes, it's for making the 2 | # Pontoon bot not try making commits to main 3 | 4 | name: Rebase pontoon branch to main 5 | on: 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | rebase: 12 | if: ${{ github.repository == 'SlimeVR/SlimeVR-Server' }} 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | ref: pontoon 21 | submodules: recursive 22 | # Get all the git history for rebasing 23 | fetch-depth: 0 24 | - name: Rebase 25 | run: | 26 | git config --local user.name "slimevr-bot" 27 | git config --local user.email 'pantoon@slimevr.dev' 28 | git fetch origin main 29 | git rebase origin/main 30 | git submodule update 31 | - name: Push rebase 32 | uses: github-actions-x/commit@v2.9 33 | with: 34 | github-token: ${{ secrets.PONTOON_BOT_KEY }} 35 | push-branch: "pontoon" 36 | commit-message: "update" 37 | force-push: "true" 38 | name: "slimevr-bot" 39 | email: "pantoon@slimevr.dev" 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Gradle project-specific cache directory 2 | .gradle 3 | 4 | # Syncthing ignore file 5 | .stignore 6 | 7 | # Ignore .idea 8 | .idea 9 | 10 | # Ignore .fleet 11 | .fleet 12 | 13 | # Ignore eclipse stuff 14 | .project 15 | .classpath 16 | .settings 17 | 18 | # VSCode stuff 19 | /.vscode/settings.json 20 | /.vscode/launch.json 21 | 22 | # Ignore eclipse stuff 23 | .project 24 | .classpath 25 | .settings 26 | 27 | # Node Stuff 28 | /node_modules 29 | .husky 30 | 31 | # kotlin stuff 32 | /.kotlin 33 | 34 | # ignore gradle build folder 35 | build/ 36 | 37 | # Rust build artifacts 38 | /target 39 | 40 | # direnv has been claimed for Nix usage 41 | .direnv/ 42 | .devenv 43 | 44 | # Ignore Android local properties 45 | local.properties 46 | 47 | # Ignore temporary config 48 | vrconfig.yml.tmp 49 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "solarxr-protocol"] 2 | path = solarxr-protocol 3 | url = https://github.com/SlimeVR/SolarXR-Protocol.git 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | YELLOW="\033[1;33m" 2 | GREEN="\033[1;32m" 3 | RESET="\033[0m" 4 | 5 | if git rev-parse -q --verify MERGE_HEAD; then 6 | echo -e "${YELLOW}Skipping precommit hook because of merge${RESET}" 7 | exit 0 8 | fi 9 | 10 | APP_PRE_COMMIT_OPTIONS="$(dirname "$0")/_/pre-commit.options" 11 | 12 | if ! [ -f "$APP_PRE_COMMIT_OPTIONS" ]; then 13 | echo -e "${YELLOW}\nSkipping pre-commit hook." 14 | echo -e "If you want to use pre-commit for lint-staged, run:\n" 15 | echo -e " ${GREEN}echo -e 'APP_LINT=true;' > ${APP_PRE_COMMIT_OPTIONS}${RESET}" 16 | echo -e "${YELLOW}\nIt will add some delay before committing!\n${RESET}" 17 | exit 0 18 | fi 19 | 20 | source $APP_PRE_COMMIT_OPTIONS 21 | 22 | if [ -n "${APP_LINT}" ] && [ "${APP_LINT}" == "true" ]; then 23 | echo -e "${GREEN}[husky] [pre-commit] [lint-staged]${RESET}" 24 | case "$(uname -sr)" in 25 | CYGWIN*|MINGW*|MINGW32*|MSYS*) 26 | npx.cmd lint-staged 27 | ;; 28 | 29 | *) 30 | npx lint-staged 31 | ;; 32 | esac 33 | fi 34 | -------------------------------------------------------------------------------- /.imgbotconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignoredFiles": ["gui/src-tauri/icons/*"] 3 | } 4 | -------------------------------------------------------------------------------- /.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | 'server/**/*.{java,kt,kts}': (filenames) => 3 | filenames.map( 4 | (filename) => 5 | `./gradlew${ 6 | process.platform === 'win32' ? '.bat' : '' 7 | } spotlessApply "-PspotlessIdeHook=${filename}"` 8 | ), 9 | }; 10 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 18.12.1 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | update-notifier=false 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | // List of extensions which should be recommended for users of this workspace. 5 | "recommendations": [ 6 | "richardwillis.vscode-spotless-gradle", 7 | "gaborv.flatbuffers", 8 | "dbaeumer.vscode-eslint", 9 | "esbenp.prettier-vscode", 10 | "rust-lang.rust-analyzer", 11 | "bradlc.vscode-tailwindcss", 12 | "EditorConfig.EditorConfig", 13 | "macabeus.vscode-fluent", 14 | "redhat.vscode-yaml" 15 | ], 16 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 17 | "unwantedRecommendations": [] 18 | } 19 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | # Use 2021 edition resolver, better resolves crate features. 3 | resolver = "2" 4 | 5 | # A list of all rust crates in the workspace. 6 | members = ["gui/src-tauri"] 7 | 8 | # These settings can be inherited by workspace members 9 | [workspace.package] 10 | edition = "2021" 11 | license = "MIT OR Apache-2.0" 12 | rust-version = "1.75" # Tauri's MSRV 13 | repository = "https://github.com/SlimeVR/SlimeVR-Server" 14 | 15 | [profile.release] 16 | lto = "thin" 17 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Eiren Rain and SlimeVR Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/img/onboarding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlimeVR/SlimeVR-Server/26f330c762f0490a4b212276554527448dc447fa/assets/img/onboarding.png -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("org.ajoberstar.grgit") 3 | } 4 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Fixes bug with spotless. See https://github.com/diffplug/spotless/issues/834#issuecomment-819118761 2 | org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ 3 | --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ 4 | --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ 5 | --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ 6 | --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED 7 | 8 | kotlin.code.style=official 9 | # https://github.com/Kotlin/kotlinx-atomicfu#atomicfu-compiler-plugin 10 | kotlinx.atomicfu.enableJvmIrTransformation=true 11 | 12 | android.useAndroidX=true 13 | android.nonTransitiveRClass=true 14 | org.gradle.unsafe.configuration-cache=false 15 | 16 | kotlinVersion=2.0.20 17 | spotlessVersion=7.0.2 18 | shadowJarVersion=8.3.2 19 | buildconfigVersion=5.5.0 20 | grgitVersion=5.2.2 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlimeVR/SlimeVR-Server/26f330c762f0490a4b212276554527448dc447fa/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gui/.env: -------------------------------------------------------------------------------- 1 | VITE_FIRMWARE_TOOL_URL=https://fw-tool-api.slimevr.io 2 | VITE_FIRMWARE_TOOL_S3_URL=https://fw-tool-bucket.slimevr.io 3 | FIRMWARE_TOOL_SCHEMA_URL=https://fw-tool-api.slimevr.io/api-json 4 | 5 | 6 | # VITE_FIRMWARE_TOOL_URL=http://localhost:3000 7 | # VITE_FIRMWARE_TOOL_S3_URL=http://localhost:9000 8 | # FIRMWARE_TOOL_SCHEMA_URL=http://localhost:3000/api-json 9 | -------------------------------------------------------------------------------- /gui/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /gui/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # JS/TS dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # Build artifacts 12 | /build 13 | /target 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | *.log 27 | 28 | # vite 29 | /dist 30 | /stats.html 31 | vite.config.ts.timestamp* 32 | 33 | # eslint 34 | .eslintcache 35 | 36 | # Sentry Config File 37 | .env.sentry-build-plugin 38 | -------------------------------------------------------------------------------- /gui/.lintstagedrc.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | '**/*.{ts,tsx}': () => 'tsc -p tsconfig.json --noEmit', 3 | 'src/**/*.{js,jsx,ts,tsx}': 'eslint --max-warnings=0 --no-warn-ignored --cache --fix', 4 | '**/*.{js,jsx,ts,tsx,css,scss,md,json}': 'prettier --write', 5 | }; 6 | -------------------------------------------------------------------------------- /gui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |9 | * Означает необходимость обязательной синхронизации этого меcта во внешних 10 | * методах. В аргументах передаётся название поля для синхронизации. 11 | *
12 | *13 | * Методы, помеченные данной аннотацией могут вызывать только Thread-Safe 14 | * методы, либо методы, помеченные такой же аннотацией с тем же полем 15 | * синхронизации. 16 | *
17 | *18 | * Поля, помеченные данной аннотацией должны быть синхронизированны на указанное 19 | * поле при чтении или записи. 20 | *
21 | * 22 | * @see {@link ThreadSafe}, {@link ThreadSecure}, {@link ThreadSafeSingle} 23 | * @author Rena 24 | */ 25 | @Retention(value = RetentionPolicy.SOURCE) 26 | public @interface Synchronize { 27 | 28 | String[] value(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /server/core/src/main/java/io/eiren/util/ann/ThreadSafe.java: -------------------------------------------------------------------------------- 1 | package io.eiren.util.ann; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | 7 | /** 8 | *9 | * Методы, помеченные этой аннотацией должны быть Thread-Safe. 10 | *
11 | *12 | * Важно: данные методы гарантированно должны обеспечивать потоковую 13 | * безопасность, но не обязаны обеспечивать концессивность (полноту данных или 14 | * точность синхронизации). 15 | *
16 | *17 | * Для полностью потоко-безопасных методов можно использовать аннотацию 18 | * {@link ThreadSecure}. 19 | *
20 | * 21 | * @see {@link ThreadSecure}, {@link Synchronize}, {@link ThreadSafeSingle} 22 | * @author Rena 23 | */ 24 | @Retention(value = RetentionPolicy.SOURCE) 25 | public @interface ThreadSafe { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /server/core/src/main/java/io/eiren/util/ann/ThreadSafeSingle.java: -------------------------------------------------------------------------------- 1 | package io.eiren.util.ann; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | 7 | /** 8 | * Соблюдает те же требования что и {@link ThreadSafe} но при условии, что сам 9 | * метод вызывается только из одного потока одновременно. 10 | * 11 | * @see {@link ThreadSafe}, {@link ThreadSecure}, {@link Synchronize} 12 | * @author Rena 13 | */ 14 | @Retention(value = RetentionPolicy.SOURCE) 15 | public @interface ThreadSafeSingle { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /server/core/src/main/java/io/eiren/util/ann/ThreadSecure.java: -------------------------------------------------------------------------------- 1 | package io.eiren.util.ann; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | 7 | /** 8 | *9 | * Методы, помеченные этой аннотацией должны быть полностью Thread-Safe. 10 | *
11 | *12 | * Важно: данные методы гарантированно должны обеспечивать потоковую 13 | * безопасность и консистентность (полноту данных и точность синхронизации). 14 | *
15 | * 16 | * @see {@link ThreadSafe}, {@link Synchronize}, {@link ThreadSafeSingle} 17 | * @author Rena 18 | */ 19 | @Retention(value = RetentionPolicy.SOURCE) 20 | public @interface ThreadSecure { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /server/core/src/main/java/io/eiren/util/collections/RemoveAtSwapFastList.java: -------------------------------------------------------------------------------- 1 | package io.eiren.util.collections; 2 | 3 | import java.util.Collection; 4 | 5 | 6 | /** 7 | * FastList that performs Remove-At-Swap on stanard remove() operations. 8 | * 9 | *
10 | * Remove operations breaks ordering of this list
11 | *
12 | * @author Rena
13 | *
14 | * @param