diff --git a/flake.lock b/flake.lock index 907e1f70c..ff17d6b89 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1692203620, - "narHash": "sha256-9SF/H8oCWv166q5o+JtV7tK+koydgFMu02HCB27UWpU=", + "lastModified": 1697058441, + "narHash": "sha256-gjtW+nkM9suMsjyid63HPmt6WZQEvuVqA5cOAf4lLM0=", "owner": "cachix", "repo": "devenv", - "rev": "eee80243720b7f284128873a9694a520d9967b2f", + "rev": "55294461a62d90c8626feca22f52b0d3d0e18e39", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1690933134, - "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", "type": "github" }, "original": { @@ -92,12 +92,30 @@ } }, "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, "locked": { - "lastModified": 1653893745, - "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { @@ -191,11 +209,11 @@ ] }, "locked": { - "lastModified": 1688922987, - "narHash": "sha256-RnQwrCD5anqWfyDAVbfFIeU+Ha6cwt5QcIwIkaGRzQw=", + "lastModified": 1697285352, + "narHash": "sha256-tRGLm/DO8+anGUCgLYxTF5EPqWv8EZ9MVFWRdh285HU=", "owner": "nlewo", "repo": "nix2container", - "rev": "ab381a7d714ebf96a83882264245dbd34f0a7ec8", + "rev": "9d7f33ef0058f4df4c0912025f43c758a3289d76", "type": "github" }, "original": { @@ -204,6 +222,25 @@ "type": "github" } }, + "nixgl": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1685908677, + "narHash": "sha256-E4zUPEUFyVWjVm45zICaHRpfGepfkE9Z2OECV9HXfA4=", + "owner": "guibou", + "repo": "nixGL", + "rev": "489d6b095ab9d289fe11af0219a9ff00fe87c7c5", + "type": "github" + }, + "original": { + "owner": "guibou", + "repo": "nixGL", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1678875422, @@ -223,11 +260,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1690881714, - "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { @@ -288,11 +325,27 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1692356644, - "narHash": "sha256-AYkPFT+CbCVSBmh0WwIzPpwhEJ4Yy3A7JZvUkGJIg5o=", + "lastModified": 1695360818, + "narHash": "sha256-JlkN3R/SSoMTa+CasbxS1gq+GpGxXQlNZRUh9+LIy/0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e35dcc04a3853da485a396bdd332217d0ac9054f", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1697456312, + "narHash": "sha256-roiSnrqb5r+ehnKCauPLugoU8S36KgmWraHgRqVYndo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8ecc900b2f695d74dea35a92f8a9f9b32c8ea33d", + "rev": "ca012a02bf8327be9e488546faecae5e05d7d749", "type": "github" }, "original": { @@ -337,7 +390,8 @@ "flake-parts": "flake-parts", "mk-shell-bin": "mk-shell-bin", "nix2container": "nix2container", - "nixpkgs": "nixpkgs_3" + "nixgl": "nixgl", + "nixpkgs": "nixpkgs_4" } }, "rust-analyzer-src": { @@ -371,6 +425,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b06d42214..963003ecd 100644 --- a/flake.nix +++ b/flake.nix @@ -7,6 +7,7 @@ nix2container.url = "github:nlewo/nix2container"; nix2container.inputs.nixpkgs.follows = "nixpkgs"; mk-shell-bin.url = "github:rrbutani/nix-mk-shell-bin"; + nixgl.url = "github:guibou/nixGL"; fenix.url = "github:nix-community/fenix"; }; @@ -15,7 +16,12 @@ extra-substituters = "https://devenv.cachix.org"; }; - outputs = inputs @ {flake-parts, ...}: + outputs = inputs @ { + self, + flake-parts, + nixgl, + ... + }: flake-parts.lib.mkFlake {inherit inputs;} { imports = [ inputs.devenv.flakeModule @@ -37,6 +43,10 @@ # Equivalent to inputs'.nixpkgs.legacyPackages.hello; # packages.default = pkgs.hello; + _module.args.pkgs = import self.inputs.nixpkgs { + inherit system; + overlays = [nixgl.overlay]; + }; devenv.shells.default = let fenixpkgs = inputs'.fenix.packages; @@ -53,6 +63,7 @@ # https://devenv.sh/reference/options/ packages = (with pkgs; [ + pkgs.nixgl.nixGLIntel cacert ]) ++ lib.optionals pkgs.stdenv.isLinux (with pkgs; [ @@ -104,7 +115,7 @@ enable = true; toolchain = fenixpkgs.fromToolchainName { name = rust_toolchain.toolchain.channel; - sha256 = "sha256-R0F0Risbr74xg9mEYydyebx/z0Wu6HI0/KWwrV30vZo="; + sha256 = "sha256-rLP8+fTxnPHoR96ZJiCa/5Ans1OojI7MLsmSqR2ip8o="; }; components = rust_toolchain.toolchain.components; }; diff --git a/gui/package.json b/gui/package.json index daf427ea4..6a8f9e62b 100644 --- a/gui/package.json +++ b/gui/package.json @@ -7,14 +7,15 @@ "@fluent/react": "^0.14.1", "@fontsource/poppins": "^4.5.8", "@formatjs/intl-localematcher": "^0.2.32", - "@react-three/fiber": "^8.10.0", - "@tauri-apps/api": "^2.0.0-alpha", - "@tauri-apps/plugin-app": "^2.0.0-alpha", - "@tauri-apps/plugin-dialog": "^2.0.0-alpha", - "@tauri-apps/plugin-fs": "^2.0.0-alpha", - "@tauri-apps/plugin-os": "^2.0.0-alpha", - "@tauri-apps/plugin-shell": "^2.0.0-alpha", - "@tauri-apps/plugin-window": "^2.0.0-alpha", + "@react-three/drei": "^9.80.3", + "@react-three/fiber": "^8.13.6", + "@tauri-apps/api": "=2.0.0-alpha.8", + "@tauri-apps/plugin-app": "=2.0.0-alpha.1", + "@tauri-apps/plugin-dialog": "=2.0.0-alpha.1", + "@tauri-apps/plugin-fs": "=2.0.0-alpha.1", + "@tauri-apps/plugin-os": "=2.0.0-alpha.2", + "@tauri-apps/plugin-shell": "=2.0.0-alpha.1", + "@tauri-apps/plugin-window": "=2.0.0-alpha.1", "@vitejs/plugin-react": "^3.0.0", "browser-fs-access": "^0.34.1", "browserslist": "^4.18.1", @@ -33,12 +34,12 @@ "react-dom": "^18.0.0", "react-helmet": "^6.1.0", "react-hook-form": "^7.29.0", - "react-modal": "3.15.1", + "react-modal": "^3.15.1", "react-responsive": "^9.0.2", "react-router-dom": "^6.2.2", "semver": "^7.5.3", "solarxr-protocol": "file:../solarxr-protocol", - "three": "^0.148.0", + "three": "^0.155.0", "ts-pattern": "^5.0.1", "typescript": "^5.1.6" }, @@ -74,13 +75,13 @@ "devDependencies": { "@dword-design/eslint-plugin-import-alias": "^4.0.8", "@tailwindcss/forms": "^0.5.3", - "@tauri-apps/cli": "^2.0.0-alpha", + "@tauri-apps/cli": "=2.0.0-alpha.17", "@types/file-saver": "^2.0.5", - "@types/react": "18.0.25", + "@types/react": "^18.0.25", "@types/react-dom": "^18.0.5", "@types/react-helmet": "^6.1.6", "@types/react-modal": "3.13.1", - "@types/three": "^0.148.0", + "@types/three": "^0.155.0", "@typescript-eslint/eslint-plugin": "^5.60.1", "@typescript-eslint/parser": "^5.60.1", "autoprefixer": "^10.4.4", @@ -92,7 +93,7 @@ "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", - "postcss": "^8.4.24", + "postcss": "^8.4.31", "prettier": "^2.8.8", "pretty-quick": "^3.1.3", "rollup-plugin-visualizer": "^5.9.2", diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl index 09feaf626..2f08478e1 100644 --- a/gui/public/i18n/en/translation.ftl +++ b/gui/public/i18n/en/translation.ftl @@ -128,6 +128,10 @@ widget-imu_visualizer-rotation_raw = Raw widget-imu_visualizer-rotation_preview = Preview widget-imu_visualizer-rotation_hide = Hide +## Widget: Skeleton Visualizer +widget-skeleton_visualizer-preview = Skeleton preview +widget-skeleton_visualizer-hide = Hide + ## Tracker status tracker-status-none = No Status tracker-status-busy = Busy diff --git a/gui/src/components/WidgetsComponent.tsx b/gui/src/components/WidgetsComponent.tsx index 882b708b7..08dd382ed 100644 --- a/gui/src/components/WidgetsComponent.tsx +++ b/gui/src/components/WidgetsComponent.tsx @@ -19,6 +19,7 @@ import { parseStatusToLocale, useStatusContext } from '@/hooks/status-system'; import { useWebsocketAPI } from '@/hooks/websocket-api'; import { useAppContext } from '@/hooks/app'; import { ClearMountingButton } from './ClearMountingButton'; +import { ToggleableSkeletonVisualizerWidget } from './widgets/SkeletonVisualizerWidget'; export function WidgetsComponent() { const { config } = useConfig(); @@ -58,6 +59,9 @@ export function WidgetsComponent() {
+
+ +
{unprioritizedStatuses.map((status) => (
- +
{!isMobile && ( diff --git a/gui/src/components/onboarding/pages/body-proportions/autobone-steps/Done.tsx b/gui/src/components/onboarding/pages/body-proportions/autobone-steps/Done.tsx index d1afaa4eb..0d2ee5542 100644 --- a/gui/src/components/onboarding/pages/body-proportions/autobone-steps/Done.tsx +++ b/gui/src/components/onboarding/pages/body-proportions/autobone-steps/Done.tsx @@ -1,6 +1,7 @@ import { Typography } from '@/components/commons/Typography'; import { useLocalization } from '@fluent/react'; import { Button } from '@/components/commons/Button'; +import { SkeletonVisualizerWidget } from '@/components/widgets/SkeletonVisualizerWidget'; export function DoneStep({ variant }: { variant: 'onboarding' | 'alone' }) { const { l10n } = useLocalization(); @@ -16,13 +17,14 @@ export function DoneStep({ variant }: { variant: 'onboarding' | 'alone' }) { -
+
{variant === 'onboarding' && ( )}
+
); } diff --git a/gui/src/components/onboarding/pages/mounting/mounting-steps/Done.tsx b/gui/src/components/onboarding/pages/mounting/mounting-steps/Done.tsx index 034fd737f..0e52e5549 100644 --- a/gui/src/components/onboarding/pages/mounting/mounting-steps/Done.tsx +++ b/gui/src/components/onboarding/pages/mounting/mounting-steps/Done.tsx @@ -1,5 +1,6 @@ import { Button } from '@/components/commons/Button'; import { Typography } from '@/components/commons/Typography'; +import { SkeletonVisualizerWidget } from '@/components/widgets/SkeletonVisualizerWidget'; import { useLocalization } from '@fluent/react'; export function DoneStep({ @@ -38,6 +39,8 @@ export function DoneStep({ )} + + ); } diff --git a/gui/src/components/tracker/TrackerSettings.tsx b/gui/src/components/tracker/TrackerSettings.tsx index 9b4077a7e..c5dfefb7c 100644 --- a/gui/src/components/tracker/TrackerSettings.tsx +++ b/gui/src/components/tracker/TrackerSettings.tsx @@ -399,7 +399,7 @@ export function TrackerSettingsPage() { type="text" name="trackerName" control={control} - autocomplete="on" + autocomplete="off" rules={undefined} label="Tracker name" > diff --git a/gui/src/components/widgets/IMUVisualizerWidget.tsx b/gui/src/components/widgets/IMUVisualizerWidget.tsx index d1623f7c4..a88df3ba0 100644 --- a/gui/src/components/widgets/IMUVisualizerWidget.tsx +++ b/gui/src/components/widgets/IMUVisualizerWidget.tsx @@ -3,24 +3,23 @@ import { TrackerDataT } from 'solarxr-protocol'; import { useTracker } from '@/hooks/tracker'; import { Typography } from '@/components/commons/Typography'; import { formatVector3 } from '@/utils/formatting'; -import { Canvas, useLoader } from '@react-three/fiber'; +import { Canvas } from '@react-three/fiber'; import * as THREE from 'three'; import { PerspectiveCamera, Vector3 } from 'three'; import { Button } from '@/components/commons/Button'; import { QuatObject } from '@/maths/quaternion'; import { useLocalization } from '@fluent/react'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { Vector3Object } from '@/maths/vector3'; +import { Gltf } from '@react-three/drei'; const groundColor = '#4444aa'; const scale = 6.5; export function TrackerModel({ model }: { model: string }) { - const gltf = useLoader(GLTFLoader, model); return ( - + ); } @@ -42,9 +41,14 @@ function SceneRenderer({ (camera as PerspectiveCamera).fov = 60; }} > - - - + + + diff --git a/gui/src/components/widgets/SkeletonVisualizerWidget.tsx b/gui/src/components/widgets/SkeletonVisualizerWidget.tsx index 85ab1a00a..eef84c1b0 100644 --- a/gui/src/components/widgets/SkeletonVisualizerWidget.tsx +++ b/gui/src/components/widgets/SkeletonVisualizerWidget.tsx @@ -1,122 +1,214 @@ -import { Canvas } from '@react-three/fiber'; +import { Canvas, Object3DNode, extend, useThree } from '@react-three/fiber'; import { useAppContext } from '@/hooks/app'; -import { Bone, PerspectiveCamera, Quaternion, Skeleton } from 'three'; -import { getHelperFromSkeleton } from 'three/examples/jsm/utils/SkeletonUtils'; -import { useMemo } from 'react'; -import { Vector3FromVec3fT } from '@/maths/vector3'; -import { QuaternionFromQuatT } from '@/maths/quaternion'; +import { Bone } from 'three'; +import { useMemo, useEffect, useRef, useState } from 'react'; +import { + OrbitControls, + OrthographicCamera, + PerspectiveCamera, +} from '@react-three/drei'; +import { + BoneKind, + createChildren, + BasedSkeletonHelper, +} from '@/utils/skeletonHelper'; +import * as THREE from 'three'; +import { BodyPart, BoneT } from 'solarxr-protocol'; +import { QuaternionFromQuatT, isIdentity } from '@/maths/quaternion'; +import classNames from 'classnames'; +import { Button } from '@/components/commons/Button'; +import { useLocalization } from '@fluent/react'; -export const threeSkeleton = (() => { - const bones = []; +extend({ BasedSkeletonHelper }); - const head = new Bone(); - const neck = new Bone(); - head.add(neck); +declare module '@react-three/fiber' { + interface ThreeElements { + basedSkeletonHelper: Object3DNode< + BasedSkeletonHelper, + typeof BasedSkeletonHelper + >; + } +} - const chest = new Bone(); - neck.add(chest); - const waist = new Bone(); - chest.add(waist); - const hip = new Bone(); - waist.add(hip); +const GROUND_COLOR = '#4444aa'; +const FRUSTUM_SIZE = 10; +const FACTOR = 2; +// Not currently used but nice to have +export function OrthographicCameraWrapper() { + const { size } = useThree(); + const aspect = useMemo(() => size.width / size.height, [size]); - const leftShoulder = new Bone(); - neck.add(leftShoulder); - const leftUpperArm = new Bone(); - leftShoulder.add(leftUpperArm); - const leftLowerArm = new Bone(); - leftUpperArm.add(leftLowerArm); - const leftHand = new Bone(); - leftLowerArm.add(leftHand); + return ( + + ); +} - const rightShoulder = new Bone(); - neck.add(rightShoulder); - const rightUpperArm = new Bone(); - rightShoulder.add(rightUpperArm); - const rightLowerArm = new Bone(); - rightUpperArm.add(rightLowerArm); - const rightHand = new Bone(); - rightLowerArm.add(rightHand); +export function SkeletonHelper({ object }: { object: Bone }) { + const { size } = useThree(); + const res = useMemo(() => new THREE.Vector2(size.width, size.height), [size]); - const leftUpperLeg = new Bone(); - hip.add(leftUpperLeg); - const leftLowerLeg = new Bone(); - leftUpperLeg.add(leftLowerLeg); - const leftFoot = new Bone(); - leftLowerLeg.add(leftFoot); + return ( + + ); +} - const rightUpperLeg = new Bone(); - hip.add(rightUpperLeg); - const rightLowerLeg = new Bone(); - rightUpperLeg.add(rightLowerLeg); - const rightFoot = new Bone(); - rightLowerLeg.add(rightFoot); +// Just need to know the length of the total body, so don't need right legs +const Y_PARTS = [ + BodyPart.NECK, + BodyPart.UPPER_CHEST, + BodyPart.CHEST, + BodyPart.WAIST, + BodyPart.HIP, + BodyPart.LEFT_UPPER_LEG, + BodyPart.LEFT_LOWER_LEG, +]; - bones.push( - head, - neck, - chest, - waist, - hip, - leftUpperLeg, - rightUpperLeg, - leftLowerLeg, - rightLowerLeg, - leftFoot, - rightFoot, - leftLowerArm, - rightLowerArm, - leftUpperArm, - rightUpperArm, - leftHand, - rightHand, - leftShoulder, - rightShoulder +interface SkeletonVisualizerWidgetProps { + height?: number | string; + maxHeight?: number | string; +} + +export function ToggleableSkeletonVisualizerWidget( + props: SkeletonVisualizerWidgetProps +) { + const { l10n } = useLocalization(); + const [enabled, setEnabled] = useState(false); + + return ( + <> + {!enabled && ( + + )} + {enabled && ( + <> + + + + )} + + ); +} + +export function SkeletonVisualizerWidget({ + height = '35vh', + maxHeight = 400, +}: SkeletonVisualizerWidgetProps) { + const { bones: _bones } = useAppContext(); + + const bones = useMemo( + () => new Map(_bones.map((b) => [b.bodyPart, b])), + [JSON.stringify(_bones)] ); - return new Skeleton(bones); -})(); + const skeleton = useRef(); -export function SkeletonVisualizerWidget() { - const { bones } = useAppContext(); + useEffect(() => { + skeleton.current = createChildren(bones, BoneKind.root); + }, [bones.size]); - const skeleton = useMemo(() => { - const skeleton = threeSkeleton.clone(); - for (const solarBone of bones) { - const bone = skeleton.bones[solarBone.bodyPart - 1]; - const localPos = bone.worldToLocal( - Vector3FromVec3fT(solarBone.headPositionG) - ); - bone.position.set(localPos.x, localPos.y, localPos.z); - - if (!bone.parent) { - bone.applyQuaternion(QuaternionFromQuatT(solarBone.rotationG)); - continue; - } - - const parentQuatInvert = bone.parent - .getWorldQuaternion(new Quaternion()) - .invert(); - bone.quaternion.multiplyQuaternions( - QuaternionFromQuatT(solarBone.rotationG), - parentQuatInvert - ); - } - return getHelperFromSkeleton(skeleton); + useEffect(() => { + skeleton.current?.forEach( + (bone) => bone instanceof BoneKind && bone.updateData(bones) + ); }, [bones]); + const heightOffset = useMemo(() => { + const hmd = bones.get(BodyPart.HEAD); + // If I know the head position, don't use an offset + if (hmd?.headPositionG?.y !== undefined && hmd.headPositionG?.y > 0) { + return 0; + } + const yLength = Y_PARTS.map((x) => bones.get(x)); + if (yLength.some((x) => x === undefined)) return 0; + return (yLength as BoneT[]).reduce((prev, cur) => prev + cur.boneLength, 0); + }, [bones]); + + const bonesInitialized = bones.size > 0; + + const targetCamera = useMemo(() => { + const hmd = bones.get(BodyPart.HEAD); + if (hmd?.headPositionG?.y && hmd.headPositionG.y > 0) { + return hmd.headPositionG.y / 2; + } + return heightOffset / 2; + }, [bonesInitialized]); + + const yawReset = useMemo(() => { + const hmd = bones.get(BodyPart.HEAD); + const chest = bones.get(BodyPart.UPPER_CHEST); + // Check if HMD is identity, if it's then use upper chest's rotation + const quat = isIdentity(hmd?.rotationG) + ? QuaternionFromQuatT(chest?.rotationG).normalize().invert() + : QuaternionFromQuatT(hmd?.rotationG).normalize().invert(); + + // Project quat to (0x, 1y, 0z) + const VEC_Y = new THREE.Vector3(0, 1, 0); + const vec = VEC_Y.multiplyScalar( + new THREE.Vector3(quat.x, quat.y, quat.z).dot(VEC_Y) / VEC_Y.lengthSq() + ); + return new THREE.Quaternion(vec.x, vec.y, vec.z, quat.w).normalize(); + }, [bonesInitialized]); + + const scale = useMemo( + () => Math.max(1.8, heightOffset) / 1.8, + [heightOffset] + ); + + if (!skeleton.current) return <>; return (
{ - (camera as PerspectiveCamera).fov = 60; - }} + className={classNames('container mx-auto')} + style={{ height, background: 'transparent', maxHeight }} > - - + + + + + +
); diff --git a/gui/src/maths/quaternion.ts b/gui/src/maths/quaternion.ts index 764f21e45..5b1597755 100644 --- a/gui/src/maths/quaternion.ts +++ b/gui/src/maths/quaternion.ts @@ -61,6 +61,11 @@ export function compareQuatT(a: QuatT | null, b: QuatT | null): boolean { return a.w === b.w && a.x === b.x && a.y === b.y && a.z === b.z; } +export function isIdentity(a?: QuatT | null): boolean { + if (!a) return false; + return a.w === 1 && a.x === 0 && a.y === 0 && a.z === 0; +} + export function similarQuaternions( a: Quaternion | null, b: Quaternion | null, diff --git a/gui/src/utils/skeletonHelper.ts b/gui/src/utils/skeletonHelper.ts new file mode 100644 index 000000000..578174b75 --- /dev/null +++ b/gui/src/utils/skeletonHelper.ts @@ -0,0 +1,355 @@ +import { Bone, Color, Matrix4, Object3D, Vector2, Vector3 } from 'three'; +import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'; +import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'; +import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry.js'; +import { BodyPart, BoneT } from 'solarxr-protocol'; +import { Vector3FromVec3fT } from '@/maths/vector3'; +import { QuaternionFromQuatT } from '@/maths/quaternion'; + +const _vector = new Vector3(); +const _boneMatrix = new Matrix4(); +const _matrixWorldInv = new Matrix4(); + +export class BasedSkeletonHelper extends LineSegments2 { + isSkeletonHelper: boolean; + root: Object3D; + bones: Bone[]; + readonly type = 'SkeletonHelper'; + + get resolution() { + return this.material.resolution; + } + set resolution(v: Vector2) { + this.material.resolution = v; + } + + constructor(object: Object3D) { + const bones = getBoneList(object); + + const geometry = new LineSegmentsGeometry(); + + const vertices = []; + const colors = []; + + const color1 = new Color(0, 0, 1); + const color2 = new Color(0, 1, 0); + + for (let i = 0; i < bones.length; i++) { + const bone = bones[i]; + + if (bone.parent && (bone.parent as Bone).isBone) { + vertices.push(0, 0, 0); + vertices.push(0, 0, 0); + if (bone.parent instanceof BoneKind) { + const color = bone.parent.boneColor; + colors.push(color.r, color.g, color.b); + colors.push(color.r, color.g, color.b); + } else { + colors.push(color1.r, color1.g, color1.b); + colors.push(color2.r, color2.g, color2.b); + } + } + } + + geometry.setPositions(vertices); + geometry.setColors(colors); + + const material = new LineMaterial({ + vertexColors: true, + // depthTest: false, + // depthWrite: false, + toneMapped: false, + transparent: true, + linewidth: 4, + }); + + super(geometry, material); + + this.isSkeletonHelper = true; + + this.root = object; + this.bones = bones; + + this.matrix = object.matrixWorld; + this.matrixAutoUpdate = false; + } + + updateMatrixWorld(force: boolean) { + const bones = this.bones; + + const geometry = this.geometry; + const vertices = []; + + _matrixWorldInv.copy(this.root.matrixWorld).invert(); + + for (let i = 0; i < bones.length; i++) { + const bone = bones[i]; + + if (bone.parent && (bone.parent as Bone).isBone) { + _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.parent.matrixWorld); + _vector.setFromMatrixPosition(_boneMatrix); + vertices.push(_vector.x, _vector.y, _vector.z); + + _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.matrixWorld); + _vector.setFromMatrixPosition(_boneMatrix); + vertices.push(_vector.x, _vector.y, _vector.z); + } + } + + geometry.setPositions(vertices); + + super.updateMatrixWorld(force); + } + + dispose() { + this.geometry.dispose(); + if (Array.isArray(this.material)) { + this.material.forEach((x) => x.dispose()); + } else { + this.material.dispose(); + } + } +} + +function getBoneList(object: Object3D): Bone[] { + const boneList: Bone[] = []; + + if ((object as Bone).isBone) { + boneList.push(object as Bone); + } + + for (let i = 0; i < object.children.length; i++) { + boneList.push(...getBoneList(object.children[i])); + } + + return boneList; +} + +export class BoneKind extends Bone { + boneT: BoneT; + tail: boolean; + + constructor(bones: Map, bodyPart: BodyPart, tail: boolean) { + super(); + const bone = bones.get(bodyPart); + if (!bone) { + throw 'Couldnt find bone ' + BodyPart[bodyPart]; + } + this.boneT = bone; + this.name = BodyPart[bodyPart]; + this.tail = tail; + this.updateData(bones); + } + + updateData(bones: Map) { + this.boneT = bones.get(this.boneT.bodyPart) ?? this.boneT; + const parent = BoneKind.parent(this.boneT.bodyPart); + const parentBone = parent === null ? undefined : bones.get(parent); + if (this.boneT.bodyPart === BoneKind.root) { + this.position.set(0, this.boneT.headPositionG?.y ?? 0, 0); + return; + } + + if (!this.tail) { + const localPosition = Vector3FromVec3fT(this.boneT.headPositionG).sub( + Vector3FromVec3fT( + parentBone === undefined + ? new Vector3(0, 0, 0) + : Vector3FromVec3fT(parentBone.headPositionG) + ) + ); + this.position.copy(localPosition); + return; + } + + const quat = QuaternionFromQuatT(this.boneT.rotationG) + // .normalize() + // .multiply( + // parentBone === undefined + // ? new Quaternion().identity() + // : QuaternionFromQuatT(parentBone.rotationG).normalize().invert().normalize() + // ) + .normalize(); + + // console.log(this.quaternion); + // console.log( + // parentBone === undefined + // ? new Vector3(0, 0, 0) + // : Vector3FromVec3fT(parentBone.headPositionG), + // Vector3FromVec3fT(this.boneT.headPositionG) + // ); + this.position.set(0, -this.boneT.boneLength, 0); + this.position.applyQuaternion(quat); + // console.log(this.position); + } + + get boneColor(): Color { + switch (this.boneT.bodyPart) { + case BodyPart.NONE: + throw 'Unexpected body part'; + case BodyPart.HEAD: + return new Color('black'); + case BodyPart.NECK: + return new Color('silver'); + case BodyPart.UPPER_CHEST: + return new Color('blue'); + case BodyPart.CHEST: + return new Color('purple'); + case BodyPart.WAIST: + return new Color('red'); + case BodyPart.HIP: + return new Color('orange'); + case BodyPart.LEFT_UPPER_LEG: + case BodyPart.RIGHT_UPPER_LEG: + return new Color('blue'); + case BodyPart.LEFT_LOWER_LEG: + case BodyPart.RIGHT_LOWER_LEG: + return new Color('teal'); + case BodyPart.LEFT_FOOT: + case BodyPart.RIGHT_FOOT: + return new Color('#00ffcc'); + case BodyPart.LEFT_LOWER_ARM: + case BodyPart.RIGHT_LOWER_ARM: + return new Color('red'); + case BodyPart.LEFT_UPPER_ARM: + case BodyPart.RIGHT_UPPER_ARM: + return new Color('indianred'); + case BodyPart.LEFT_HAND: + case BodyPart.RIGHT_HAND: + return new Color('fuchsia'); + case BodyPart.LEFT_SHOULDER: + case BodyPart.RIGHT_SHOULDER: + return new Color('#00ffff'); + case BodyPart.LEFT_HIP: + case BodyPart.RIGHT_HIP: + return new Color('pink'); + } + } + + static root: BodyPart = BodyPart.HEAD; + + static children(part: BodyPart): BodyPart[] { + switch (part) { + case BodyPart.NONE: + throw 'Unexpected body part'; + case BodyPart.HEAD: + return [BodyPart.NECK]; + case BodyPart.NECK: + return [BodyPart.UPPER_CHEST, BodyPart.LEFT_SHOULDER, BodyPart.RIGHT_SHOULDER]; + case BodyPart.UPPER_CHEST: + return [BodyPart.CHEST]; + case BodyPart.CHEST: + return [BodyPart.WAIST]; + case BodyPart.WAIST: + return [BodyPart.HIP]; + case BodyPart.HIP: + return [BodyPart.LEFT_HIP, BodyPart.RIGHT_HIP]; + + case BodyPart.LEFT_HIP: + return [BodyPart.LEFT_UPPER_LEG]; + case BodyPart.RIGHT_HIP: + return [BodyPart.RIGHT_UPPER_LEG]; + case BodyPart.LEFT_UPPER_LEG: + return [BodyPart.LEFT_LOWER_LEG]; + case BodyPart.RIGHT_UPPER_LEG: + return [BodyPart.RIGHT_LOWER_LEG]; + case BodyPart.LEFT_LOWER_LEG: + return [BodyPart.LEFT_FOOT]; + case BodyPart.RIGHT_LOWER_LEG: + return [BodyPart.RIGHT_FOOT]; + case BodyPart.LEFT_FOOT: + return []; + case BodyPart.RIGHT_FOOT: + return []; + + case BodyPart.LEFT_SHOULDER: + return [BodyPart.LEFT_UPPER_ARM]; + case BodyPart.RIGHT_SHOULDER: + return [BodyPart.RIGHT_UPPER_ARM]; + case BodyPart.LEFT_UPPER_ARM: + return [BodyPart.LEFT_LOWER_ARM]; + case BodyPart.RIGHT_UPPER_ARM: + return [BodyPart.RIGHT_LOWER_ARM]; + case BodyPart.LEFT_LOWER_ARM: + return [BodyPart.LEFT_HAND]; + case BodyPart.RIGHT_LOWER_ARM: + return [BodyPart.RIGHT_HAND]; + case BodyPart.LEFT_HAND: + return []; + case BodyPart.RIGHT_HAND: + return []; + } + } + + static parent(part: BodyPart): BodyPart | null { + switch (part) { + case BodyPart.NONE: + throw 'Unexpected body part'; + case BodyPart.HEAD: + return null; + case BodyPart.NECK: + return BodyPart.HEAD; + case BodyPart.UPPER_CHEST: + return BodyPart.NECK; + case BodyPart.CHEST: + return BodyPart.UPPER_CHEST; + case BodyPart.WAIST: + return BodyPart.CHEST; + case BodyPart.HIP: + return BodyPart.WAIST; + + case BodyPart.LEFT_HIP: + case BodyPart.RIGHT_HIP: + return BodyPart.HIP; + case BodyPart.LEFT_UPPER_LEG: + return BodyPart.LEFT_HIP; + case BodyPart.RIGHT_UPPER_LEG: + return BodyPart.RIGHT_HIP; + case BodyPart.LEFT_LOWER_LEG: + return BodyPart.LEFT_UPPER_LEG; + case BodyPart.RIGHT_LOWER_LEG: + return BodyPart.RIGHT_UPPER_LEG; + case BodyPart.LEFT_FOOT: + return BodyPart.LEFT_LOWER_LEG; + case BodyPart.RIGHT_FOOT: + return BodyPart.RIGHT_LOWER_LEG; + + case BodyPart.LEFT_SHOULDER: + case BodyPart.RIGHT_SHOULDER: + return BodyPart.NECK; + case BodyPart.LEFT_UPPER_ARM: + return BodyPart.LEFT_SHOULDER; + case BodyPart.RIGHT_UPPER_ARM: + return BodyPart.RIGHT_SHOULDER; + case BodyPart.LEFT_LOWER_ARM: + return BodyPart.LEFT_UPPER_ARM; + case BodyPart.RIGHT_LOWER_ARM: + return BodyPart.RIGHT_UPPER_ARM; + case BodyPart.LEFT_HAND: + return BodyPart.LEFT_LOWER_ARM; + case BodyPart.RIGHT_HAND: + return BodyPart.RIGHT_LOWER_ARM; + } + } +} + +export function createChildren( + bones: Map, + body: BodyPart, + parentBone?: BoneKind +): (BoneKind | Bone)[] { + if (bones.size === 0) return [new Bone()]; + const childrenBodies = BoneKind.children(body); + const parent = new BoneKind(bones, body, false); + parentBone?.add(parent); + if (childrenBodies.length === 0) { + const tail = new BoneKind(bones, body, true); + parent.add(tail); + return [parent, tail]; + } + + const children = childrenBodies.flatMap((bodyPart) => + createChildren(bones, bodyPart, parent) + ); + return [parent, ...children]; +} diff --git a/package-lock.json b/package-lock.json index f6ed6f536..4fe96179b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,20 +17,22 @@ } }, "gui": { + "name": "slimevr-ui", "version": "0.5.1", "dependencies": { "@fluent/bundle": "^0.17.1", "@fluent/react": "^0.14.1", "@fontsource/poppins": "^4.5.8", "@formatjs/intl-localematcher": "^0.2.32", - "@react-three/fiber": "^8.10.0", - "@tauri-apps/api": "^2.0.0-alpha", - "@tauri-apps/plugin-app": "^2.0.0-alpha", - "@tauri-apps/plugin-dialog": "^2.0.0-alpha", - "@tauri-apps/plugin-fs": "^2.0.0-alpha", - "@tauri-apps/plugin-os": "^2.0.0-alpha", - "@tauri-apps/plugin-shell": "^2.0.0-alpha", - "@tauri-apps/plugin-window": "^2.0.0-alpha", + "@react-three/drei": "^9.80.3", + "@react-three/fiber": "^8.13.6", + "@tauri-apps/api": "=2.0.0-alpha.8", + "@tauri-apps/plugin-app": "=2.0.0-alpha.1", + "@tauri-apps/plugin-dialog": "=2.0.0-alpha.1", + "@tauri-apps/plugin-fs": "=2.0.0-alpha.1", + "@tauri-apps/plugin-os": "=2.0.0-alpha.2", + "@tauri-apps/plugin-shell": "=2.0.0-alpha.1", + "@tauri-apps/plugin-window": "=2.0.0-alpha.1", "@vitejs/plugin-react": "^3.0.0", "browser-fs-access": "^0.34.1", "browserslist": "^4.18.1", @@ -49,25 +51,25 @@ "react-dom": "^18.0.0", "react-helmet": "^6.1.0", "react-hook-form": "^7.29.0", - "react-modal": "3.15.1", + "react-modal": "^3.15.1", "react-responsive": "^9.0.2", "react-router-dom": "^6.2.2", "semver": "^7.5.3", "solarxr-protocol": "file:../solarxr-protocol", - "three": "^0.148.0", + "three": "^0.155.0", "ts-pattern": "^5.0.1", "typescript": "^5.1.6" }, "devDependencies": { "@dword-design/eslint-plugin-import-alias": "^4.0.8", "@tailwindcss/forms": "^0.5.3", - "@tauri-apps/cli": "^2.0.0-alpha", + "@tauri-apps/cli": "=2.0.0-alpha.17", "@types/file-saver": "^2.0.5", - "@types/react": "18.0.25", + "@types/react": "^18.0.25", "@types/react-dom": "^18.0.5", "@types/react-helmet": "^6.1.6", "@types/react-modal": "3.13.1", - "@types/three": "^0.148.0", + "@types/three": "^0.155.0", "@typescript-eslint/eslint-plugin": "^5.60.1", "@typescript-eslint/parser": "^5.60.1", "autoprefixer": "^10.4.4", @@ -79,7 +81,7 @@ "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", - "postcss": "^8.4.24", + "postcss": "^8.4.31", "prettier": "^2.8.8", "pretty-quick": "^3.1.3", "rollup-plugin-visualizer": "^5.9.2", @@ -2135,9 +2137,9 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dependencies": { "@babel/code-frame": "^7.22.13", "@babel/generator": "^7.23.0", @@ -2167,6 +2169,35 @@ "node": ">=6.9.0" } }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", + "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", + "dependencies": { + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", + "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", + "dependencies": { + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/types": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", + "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" + }, + "node_modules/@chevrotain/utils": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", + "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" + }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -3035,6 +3066,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mediapipe/tasks-vision": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.2.tgz", + "integrity": "sha512-d8Q9uRK89ZRWmED2JLI9/blpJcfdbh0iEUuMo8TgkMzNfQBY1/GC0FEJWrairTwHkxIf6Oud1vFBP+aHicWqJA==" + }, "node_modules/@mgit-at/typescript-flatbuffers-codegen": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@mgit-at/typescript-flatbuffers-codegen/-/typescript-flatbuffers-codegen-0.1.3.tgz", @@ -3218,6 +3254,114 @@ "node": ">= 8" } }, + "node_modules/@react-spring/animated": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz", + "integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==", + "dependencies": { + "@react-spring/shared": "~9.6.1", + "@react-spring/types": "~9.6.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz", + "integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==", + "dependencies": { + "@react-spring/animated": "~9.6.1", + "@react-spring/rafz": "~9.6.1", + "@react-spring/shared": "~9.6.1", + "@react-spring/types": "~9.6.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/rafz": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz", + "integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==" + }, + "node_modules/@react-spring/shared": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz", + "integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==", + "dependencies": { + "@react-spring/rafz": "~9.6.1", + "@react-spring/types": "~9.6.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/three": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.6.1.tgz", + "integrity": "sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==", + "dependencies": { + "@react-spring/animated": "~9.6.1", + "@react-spring/core": "~9.6.1", + "@react-spring/shared": "~9.6.1", + "@react-spring/types": "~9.6.1" + }, + "peerDependencies": { + "@react-three/fiber": ">=6.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "three": ">=0.126" + } + }, + "node_modules/@react-spring/types": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz", + "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==" + }, + "node_modules/@react-three/drei": { + "version": "9.80.3", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.80.3.tgz", + "integrity": "sha512-pavkh2qjyh3luf3X2NNMsTyzAW+vS0EmapRQoHUO/au3ha/Ag1JKX83p891O0fV5ne7I+Fet/cEzh8rAfhd+Wg==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@mediapipe/tasks-vision": "0.10.2", + "@react-spring/three": "~9.6.1", + "@use-gesture/react": "^10.2.24", + "camera-controls": "^2.4.2", + "detect-gpu": "^5.0.28", + "glsl-noise": "^0.0.0", + "lodash.clamp": "^4.0.3", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "maath": "^0.6.0", + "meshline": "^3.1.6", + "react-composer": "^5.0.3", + "react-merge-refs": "^1.1.0", + "stats-gl": "^1.0.4", + "stats.js": "^0.17.0", + "suspend-react": "^0.1.3", + "three-mesh-bvh": "^0.6.0", + "three-stdlib": "^2.23.9", + "troika-three-text": "^0.47.2", + "utility-types": "^3.10.0", + "zustand": "^3.5.13" + }, + "peerDependencies": { + "@react-three/fiber": ">=8.0", + "react": ">=18.0", + "react-dom": ">=18.0", + "three": ">=0.137" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, "node_modules/@react-three/fiber": { "version": "8.14.3", "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.14.3.tgz", @@ -3304,9 +3448,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-alpha.14.tgz", - "integrity": "sha512-4/IQwN5S94D6LTXQrDWbSea0pGb9TTC4BwxHUFmhep4NjFxms161v1zadAUIsq/N2x6WwCBGrsdq9SIkgKv49Q==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-alpha.17.tgz", + "integrity": "sha512-fXz1KQzolqHY40bmNa/mzrdid4zlIaI/catXN8iqSO/1aNXNpLhg+6PWrwW5foiD7kJ6lgLlCtICW/1jRE5BZg==", "dev": true, "bin": { "tauri": "tauri.js" @@ -3319,22 +3463,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.0.0-alpha.14", - "@tauri-apps/cli-darwin-x64": "2.0.0-alpha.14", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-alpha.14", - "@tauri-apps/cli-linux-arm64-gnu": "2.0.0-alpha.14", - "@tauri-apps/cli-linux-arm64-musl": "2.0.0-alpha.14", - "@tauri-apps/cli-linux-x64-gnu": "2.0.0-alpha.14", - "@tauri-apps/cli-linux-x64-musl": "2.0.0-alpha.14", - "@tauri-apps/cli-win32-arm64-msvc": "2.0.0-alpha.14", - "@tauri-apps/cli-win32-ia32-msvc": "2.0.0-alpha.14", - "@tauri-apps/cli-win32-x64-msvc": "2.0.0-alpha.14" + "@tauri-apps/cli-darwin-arm64": "2.0.0-alpha.17", + "@tauri-apps/cli-darwin-x64": "2.0.0-alpha.17", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-alpha.17", + "@tauri-apps/cli-linux-arm64-gnu": "2.0.0-alpha.17", + "@tauri-apps/cli-linux-arm64-musl": "2.0.0-alpha.17", + "@tauri-apps/cli-linux-x64-gnu": "2.0.0-alpha.17", + "@tauri-apps/cli-linux-x64-musl": "2.0.0-alpha.17", + "@tauri-apps/cli-win32-arm64-msvc": "2.0.0-alpha.17", + "@tauri-apps/cli-win32-ia32-msvc": "2.0.0-alpha.17", + "@tauri-apps/cli-win32-x64-msvc": "2.0.0-alpha.17" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-alpha.14.tgz", - "integrity": "sha512-3K416rvSUt8el/fdPnSnHJOI2j5Os9Kyy17XZp+z3PKRRuo/iJPp9L3w0zFGYsh7C+ylzV4OBUSVTi+e+gO5qA==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-alpha.17.tgz", + "integrity": "sha512-WDqekRiVwMu/hKsf/xBHcfi/YZ7X9o6Piy4Qolt+YYyfi4wh5ZYZnom+7kIZBlSCc32gtXGViBXEivhcKzFQ3w==", "cpu": [ "arm64" ], @@ -3348,9 +3492,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-alpha.14.tgz", - "integrity": "sha512-aLEUGG8Z0UpTENe4/UG6DU8bnB2e1uxyxYvcmFKrHv+EAtR9nLH14alBxPl2K54YXy3JLR4bKROW15a/sFrX9g==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-alpha.17.tgz", + "integrity": "sha512-WcQ+iSIaxr80gpa+ji+4e7dD0w/s3VCo29DU3wT/uQBKrCfkJUwmUAqEwyrR7INWcOurLF0IizR71In3NrYJiw==", "cpu": [ "x64" ], @@ -3364,9 +3508,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-alpha.14.tgz", - "integrity": "sha512-Lu7unNvurBccxfHIaUQ0gPgUioTkQBMtWGrqO/auZ/JbjPR1W2eBlRwVNXf+nBWX9HwomPR3YD5yZuZmzxRV2g==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-alpha.17.tgz", + "integrity": "sha512-xgVc3Pv0Wf7aWqi0eH1iEemi9uQJJfMCVqBjPrK65Bm1LsBmMw99QS5YH8XPCMfB01Jfdzf3Ty9ZCW8/vjqz3w==", "cpu": [ "arm" ], @@ -3380,9 +3524,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-alpha.14.tgz", - "integrity": "sha512-g8HkwKvAsWLLMJzPup7B1BCilYmXKwXdee7sf8QFbaIUSccR8i5pXLK5N/quKw5lmldYgFveEyuW9Qs8RgTYnQ==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-alpha.17.tgz", + "integrity": "sha512-QEx92085i+I4lOdboJ0PK+DSrlHq613HTqiSO4YteD5uCXsq2R9uAcFXM08quQYpRl4b9GeG99vig5GDOZMOkw==", "cpu": [ "arm64" ], @@ -3396,9 +3540,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-alpha.14.tgz", - "integrity": "sha512-ag4UuX6zg7vmBFWmg9ChyiJI7GTMkc8tjr/qobd3Lg9ddmjnVWwLUHt6v1kYhXiU7iLPD5DYDIjU8x/POc3hSA==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-alpha.17.tgz", + "integrity": "sha512-Iq0YHtg1yOvx3xxne6aHRS46SG6o6aQPACORGcJneGL6UjOQ7M34zKI9fX2tOWB5YEcVZBOvtNEZQOUeG2bw7g==", "cpu": [ "arm64" ], @@ -3412,9 +3556,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-alpha.14.tgz", - "integrity": "sha512-+CviROc4fzrGqqyHQXh3uc2dGr/oYr19I8r2k+LJ2CDfmtj7CbNd/oC5oehHbHdw1oGFKuDPudrTGvzdRNygYA==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-alpha.17.tgz", + "integrity": "sha512-CAdd2EhGsFWu3nr0o650dfTLOJhICRoqETKmAgSEpQNtpXuJwrqxA3XrIa1sUkgWZacf3dgQwyNNlvB8oYOHKg==", "cpu": [ "x64" ], @@ -3428,9 +3572,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-alpha.14.tgz", - "integrity": "sha512-aCP51HOAQXgVhyPHXKy627bYVRkNnpCvSU3L03pYV8YDoGo+veeuek5UiW7PlNdwx52B/yC3Jz7Dr3gEbFimfQ==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-alpha.17.tgz", + "integrity": "sha512-xMhqAvcD0+b7creRhf7XnMTeoMAmmp1FvtNfosWCdWl7o9YHkqyNlkSp9rn96lhP2DG/Ew2CHxKOZaPql9gnlw==", "cpu": [ "x64" ], @@ -3444,9 +3588,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-alpha.14.tgz", - "integrity": "sha512-b6Ei5ERUF0KS1bttM7i6U62GmjIvlgK03XZqvL/KLNvUfqRMu8F7JA1ejSExgTxhEhKSWA768HiTXpXk2GjFFw==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-alpha.17.tgz", + "integrity": "sha512-j8Q6JkDGW1N8brMjg74/AkVwyg14VVfQUFoai9Ocbf8q9gGNE5IRr7KvbWjqDntUihbc7MURwcXjcsJ4duYe/A==", "cpu": [ "arm64" ], @@ -3460,9 +3604,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-alpha.14.tgz", - "integrity": "sha512-TDkvu5pd37bKxZ6N+BqngCNGcefY7aHxyJ3BdBGxF+wRMjEMh70mgEXk8i0uM/aUi/Kl1GQoO6xJfUDlIMPXOA==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-alpha.17.tgz", + "integrity": "sha512-YIdSHH2Y9Rcg8Z5WoRUTlEi1DZj/Okrz4q0b+z8xwJQFSGsxUhpc3U81iBW1yw/7AtXiLtzr8AiBrLAw4ZYGHA==", "cpu": [ "ia32" ], @@ -3476,9 +3620,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.0.0-alpha.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-alpha.14.tgz", - "integrity": "sha512-9yfoEe2RSykKr5hCifVAL5o0gHXgRCS+Wo+RJjQ9L2+QHY7XPLZYAhj/h8jdcAdRveyIQwat3k7wl+SW87v1eg==", + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-alpha.17.tgz", + "integrity": "sha512-+1stlGdRdiuyU+q1AlqieZhD2WpdLuP8EZxv2KbbjifLDt6fg1FUrcocmpIa8qsrXue7vg2sTrWNuy4aq/v4bw==", "cpu": [ "x64" ], @@ -3623,6 +3767,16 @@ "url": "https://opencollective.com/tauri" } }, + "node_modules/@tweenjs/tween.js": { + "version": "18.6.4", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz", + "integrity": "sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==" + }, + "node_modules/@types/draco3d": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.2.tgz", + "integrity": "sha512-goh23EGr6CLV6aKPwN1p8kBD/7tT5V/bLpToSbarKrwVejqNrspVrv8DhliteYkkhZYrlq/fwKZRRUzH4XN88w==" + }, "node_modules/@types/eslint": { "version": "8.44.3", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", @@ -3677,6 +3831,11 @@ "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==", "peer": true }, + "node_modules/@types/offscreencanvas": { + "version": "2019.7.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", + "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -3742,20 +3901,28 @@ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==" }, + "node_modules/@types/stats.js": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.0.tgz", + "integrity": "sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==" + }, "node_modules/@types/three": { - "version": "0.148.1", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.148.1.tgz", - "integrity": "sha512-gZwIyTBMxKXqJHXmZ0dzvDieuQ4hz8MPNHtkRrAwER/xPlAh9eP2WIfaolvQY+wJAzlNV5a9ceS4JT+i/jybsw==", - "dev": true, + "version": "0.155.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.155.0.tgz", + "integrity": "sha512-IzdbqXsGsbG0flvq9D5L9pZRwySQQps2bGcizLYEsfvK3dM+B0sqKR6S+xAOXbouXemfDmHttrcQjVOM46YnAw==", "dependencies": { - "@types/webxr": "*" + "@tweenjs/tween.js": "~18.6.4", + "@types/stats.js": "*", + "@types/webxr": "*", + "fflate": "~0.6.9", + "lil-gui": "~0.17.0", + "meshoptimizer": "~0.18.1" } }, "node_modules/@types/webxr": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.5.tgz", - "integrity": "sha512-HVOsSRTQYx3zpVl0c0FBmmmcY/60BkQLzVnpE9M1aG4f2Z0aKlBWfj4XZ2zr++XNBfkQWYcwhGlmuu44RJPDqg==", - "dev": true + "integrity": "sha512-HVOsSRTQYx3zpVl0c0FBmmmcY/60BkQLzVnpE9M1aG4f2Z0aKlBWfj4XZ2zr++XNBfkQWYcwhGlmuu44RJPDqg==" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", @@ -3955,6 +4122,22 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@use-gesture/core": { + "version": "10.2.27", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.2.27.tgz", + "integrity": "sha512-V4XV7hn9GAD2MYu8yBBVi5iuWBsAMfjPRMsEVzoTNGYH72tf0kFP+OKqGKc8YJFQIJx6yj+AOqxmEHOmx2/MEA==" + }, + "node_modules/@use-gesture/react": { + "version": "10.2.27", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.2.27.tgz", + "integrity": "sha512-7E5vnWCxeslWlxwZ8uKIcnUZVMTRMZ8cvSnLLKF1NkyNb3PnNiAzoXM4G1vTKJKRhgOTeI6wK1YsEpwo9ABV5w==", + "dependencies": { + "@use-gesture/core": "10.2.27" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, "node_modules/@vitejs/plugin-react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz", @@ -4622,6 +4805,14 @@ } ] }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -4728,6 +4919,14 @@ "node": ">= 6" } }, + "node_modules/camera-controls": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.7.0.tgz", + "integrity": "sha512-HONMoMYHieOCQOoweS639bdWHP/P/fvVGR08imnECGVUp04mqGfsX/zp1ZufLeiAA5hA6i1JhP6SrnOwh01C0w==", + "peerDependencies": { + "three": ">=0.126.1" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001539", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001539.tgz", @@ -4759,6 +4958,19 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chevrotain": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", + "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", + "dependencies": { + "@chevrotain/cst-dts-gen": "10.5.0", + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "@chevrotain/utils": "10.5.0", + "lodash": "4.17.21", + "regexp-to-ast": "0.5.0" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -5276,6 +5488,14 @@ "node": ">=6" } }, + "node_modules/detect-gpu": { + "version": "5.0.36", + "resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.36.tgz", + "integrity": "sha512-fc+ylg9AnplrKW3POCQhyJ93bjsJK3AzxP5RI9hnRvHzGit8kWN38LLIivzNMCX80EaXFok/1P2+KZXZVbZgoA==", + "dependencies": { + "webgl-constants": "^1.1.1" + } + }, "node_modules/detect-port-alt": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", @@ -5348,6 +5568,11 @@ "node": ">=6.0.0" } }, + "node_modules/draco3d": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.6.tgz", + "integrity": "sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==" + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -6322,6 +6547,11 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", + "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -6837,6 +7067,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/glsl-noise": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz", + "integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==" + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -7622,6 +7857,11 @@ "node": ">=6" } }, + "node_modules/ktx-parse": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.4.5.tgz", + "integrity": "sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg==" + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -7647,6 +7887,11 @@ "node": ">= 0.8.0" } }, + "node_modules/lil-gui": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz", + "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==" + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -7749,6 +7994,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.clamp": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/lodash.clamp/-/lodash.clamp-4.0.3.tgz", + "integrity": "sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -7759,6 +8009,16 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==" + }, "node_modules/log-update": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", @@ -7797,6 +8057,15 @@ "yallist": "^3.0.2" } }, + "node_modules/maath": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/maath/-/maath-0.6.0.tgz", + "integrity": "sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==", + "peerDependencies": { + "@types/three": ">=0.144.0", + "three": ">=0.144.0" + } + }, "node_modules/magic-string": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", @@ -7846,6 +8115,19 @@ "node": ">= 8" } }, + "node_modules/meshline": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.1.6.tgz", + "integrity": "sha512-8JZJOdaL5oz3PI/upG8JvP/5FfzYUOhrkJ8np/WKvXzl0/PZ2V9pqTvCIjSKv+w9ccg2xb+yyBhXAwt6ier3ug==", + "peerDependencies": { + "three": ">=0.137" + } + }, + "node_modules/meshoptimizer": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==" + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -7919,6 +8201,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mmd-parser": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mmd-parser/-/mmd-parser-1.0.4.tgz", + "integrity": "sha512-Qi0VCU46t2IwfGv5KF0+D/t9cizcDug7qnNoy9Ggk7aucp0tssV8IwTMkBlDbm+VqAf3cdQHTCARKSsuS2MYFg==" + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -8220,6 +8507,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/opentype.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz", + "integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==", + "dependencies": { + "string.prototype.codepointat": "^0.2.1", + "tiny-inflate": "^1.0.3" + }, + "bin": { + "ot": "bin/ot" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -8463,9 +8765,9 @@ } }, "node_modules/postcss": { - "version": "8.4.30", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz", - "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -9130,6 +9432,11 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/potpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", + "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9469,6 +9776,17 @@ "node": ">=0.10.0" } }, + "node_modules/react-composer": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz", + "integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==", + "dependencies": { + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -9647,6 +9965,15 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "node_modules/react-merge-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz", + "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, "node_modules/react-modal": { "version": "3.15.1", "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.15.1.tgz", @@ -9834,6 +10161,11 @@ "@babel/runtime": "^7.8.4" } }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -10479,6 +10811,16 @@ "node": ">=0.10.0" } }, + "node_modules/stats-gl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-1.0.4.tgz", + "integrity": "sha512-oxo13HHonoMWIYcrIu4xCk8IcFEFaqAOkMOMIyfvZFxNZzGy+jnW8sy0W3VfEjKQd5JX0Kp2KhePAKhtI6/TSw==" + }, + "node_modules/stats.js": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz", + "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==" + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -10522,6 +10864,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" + }, "node_modules/string.prototype.matchall": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", @@ -10868,9 +11215,43 @@ } }, "node_modules/three": { - "version": "0.148.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.148.0.tgz", - "integrity": "sha512-8uzVV+qhTPi0bOFs/3te3RW6hb3urL8jYEl6irjCWo/l6sr8MPNMcClFev/MMYeIxr0gmDcoXTy/8LXh/LXkfw==" + "version": "0.155.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.155.0.tgz", + "integrity": "sha512-sNgCYmDijnIqkD/bMfk+1pHg3YzsxW7V2ChpuP6HCQ8NiZr3RufsXQr8M3SSUMjW4hG+sUk7YbyuY0DncaDTJQ==" + }, + "node_modules/three-mesh-bvh": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.6.3.tgz", + "integrity": "sha512-xjuGLSI9nBATIsWcT/DnnNma5xXYyvBiXfUbhGLAFqItOlOKYF5JWsUOX+cuSAnSWovEoHzd5Emx23qKiByrlw==", + "peerDependencies": { + "three": ">= 0.151.0" + } + }, + "node_modules/three-stdlib": { + "version": "2.24.2", + "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.24.2.tgz", + "integrity": "sha512-+FWg+evDvjcuwIYopqEz6xCrqadSW6j855EV4/5w/kygwEc2BktB7s4Y8iZEQKGq8g6Srfj5eWQpSK0+51C4Hg==", + "dependencies": { + "@types/draco3d": "^1.4.0", + "@types/offscreencanvas": "^2019.6.4", + "@types/webxr": "^0.5.2", + "chevrotain": "^10.1.2", + "draco3d": "^1.4.1", + "fflate": "^0.6.9", + "ktx-parse": "^0.4.5", + "mmd-parser": "^1.0.4", + "opentype.js": "^1.3.3", + "potpack": "^1.0.1", + "zstddec": "^0.0.2" + }, + "peerDependencies": { + "three": ">=0.128.0" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" }, "node_modules/tinycolor2": { "version": "1.6.0", @@ -10897,6 +11278,33 @@ "node": ">=8.0" } }, + "node_modules/troika-three-text": { + "version": "0.47.2", + "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.47.2.tgz", + "integrity": "sha512-qylT0F+U7xGs+/PEf3ujBdJMYWbn0Qci0kLqI5BJG2kW1wdg4T1XSxneypnF05DxFqJhEzuaOR9S2SjiyknMng==", + "dependencies": { + "bidi-js": "^1.0.2", + "troika-three-utils": "^0.47.2", + "troika-worker-utils": "^0.47.2", + "webgl-sdf-generator": "1.1.1" + }, + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-three-utils": { + "version": "0.47.2", + "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.47.2.tgz", + "integrity": "sha512-/28plhCxfKtH7MSxEGx8e3b/OXU5A0xlwl+Sbdp0H8FXUHKZDoksduEKmjQayXYtxAyuUiCRunYIv/8Vi7aiyg==", + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-worker-utils": { + "version": "0.47.2", + "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.47.2.tgz", + "integrity": "sha512-mzss4MeyzUkYBppn4x5cdAqrhBHFEuVmMMgLMTyFV23x6GvQMyo+/R5E5Lsbrt7WSt5RfvewjcwD1DChRTA9lA==" + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -11182,6 +11590,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "engines": { + "node": ">= 4" + } + }, "node_modules/vite": { "version": "4.4.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", @@ -11257,6 +11673,16 @@ "node": ">=10.13.0" } }, + "node_modules/webgl-constants": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz", + "integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==" + }, + "node_modules/webgl-sdf-generator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz", + "integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==" + }, "node_modules/webpack": { "version": "5.88.2", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", @@ -11559,6 +11985,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zstddec": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.0.2.tgz", + "integrity": "sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==" + }, "node_modules/zustand": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d13ee540f..559394342 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.71.1" +channel = "1.73" profile = "default" components = ["rust-analyzer", "rust-src"]