diff --git a/package-lock.json b/package-lock.json index c326e41..b1a12a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@monaco-editor/react": "^4.7.0", "@tailwindcss/vite": "^4.3.0", + "@types/three": "^0.181.0", "@vitejs/plugin-react": "^4.4.1", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", @@ -23,6 +24,7 @@ "remark-gfm": "^4.0.1", "socket.io-client": "^4.8.3", "tailwindcss": "^4.3.0", + "three": "^0.181.2", "vite": "^6.3.5" }, "devDependencies": { @@ -295,6 +297,12 @@ "node": ">=6.9.0" } }, + "node_modules/@dimforge/rapier3d-compat": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", + "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", + "license": "Apache-2.0" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -1424,6 +1432,12 @@ "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1542,6 +1556,27 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/stats.js": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.181.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.181.0.tgz", + "integrity": "sha512-MLF1ks8yRM2k71D7RprFpDb9DOX0p22DbdPqT/uAkc6AtQXjxWCVDjCy23G9t1o8HcQPk7woD2NIyiaWcWPYmA==", + "license": "MIT", + "dependencies": { + "@dimforge/rapier3d-compat": "~0.12.0", + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": "*", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~0.22.0" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -1555,6 +1590,12 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, + "node_modules/@types/webxr": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "license": "MIT" + }, "node_modules/@ungap/structured-clone": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", @@ -1581,6 +1622,12 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@webgpu/types": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.71.tgz", + "integrity": "sha512-mMy8/ODcKhab808co15eW+yN+HgXoQxRQHTiBV9Mrvl1r0ufnid7YOcI+gi4eUWSWl9ezD6TW2KXccrL8HCh2A==", + "license": "BSD-3-Clause" + }, "node_modules/@xterm/addon-fit": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0.tgz", @@ -1968,6 +2015,12 @@ } } }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "license": "MIT" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2738,6 +2791,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/meshoptimizer": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.22.0.tgz", + "integrity": "sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==", + "license": "MIT" + }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -3755,6 +3814,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/three": { + "version": "0.181.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.181.2.tgz", + "integrity": "sha512-k/CjiZ80bYss6Qs7/ex1TBlPD11whT9oKfT8oTGiHa34W4JRd1NiH/Tr1DbHWQ2/vMUypxksLnF2CfmlmM5XFQ==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", diff --git a/package.json b/package.json index 3672f05..a9b775d 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dependencies": { "@monaco-editor/react": "^4.7.0", "@tailwindcss/vite": "^4.3.0", + "@types/three": "^0.181.0", "@vitejs/plugin-react": "^4.4.1", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", @@ -24,6 +25,7 @@ "remark-gfm": "^4.0.1", "socket.io-client": "^4.8.3", "tailwindcss": "^4.3.0", + "three": "^0.181.2", "vite": "^6.3.5" }, "devDependencies": { diff --git a/public/slam-viewer/assets/mk-mini.glb b/public/slam-viewer/assets/mk-mini.glb new file mode 100644 index 0000000..c14e23d Binary files /dev/null and b/public/slam-viewer/assets/mk-mini.glb differ diff --git a/public/slam-viewer/index.html b/public/slam-viewer/index.html index b97b190..e2c6a83 100644 --- a/public/slam-viewer/index.html +++ b/public/slam-viewer/index.html @@ -14,7 +14,7 @@ width:260px; height:220px; z-index:10; - background:#62736f; + background:#111520; border:1px solid rgba(0,0,0,.45); pointer-events:none; } @@ -55,7 +55,14 @@ gap:7px; align-items:flex-start; } - #keyGuide { + #topLeftControls { + position:absolute; + left:16px; + top:16px; + z-index:10; + display:none; + } + #keyGuide { position:absolute; left:16px; bottom:16px; @@ -67,14 +74,56 @@ font:11px/1.35 sans-serif; pointer-events:none; backdrop-filter:blur(8px); - box-shadow:0 10px 28px rgba(0,0,0,.16); - } + box-shadow:0 10px 28px rgba(0,0,0,.16); + } + #responseWaitOverlay { + position:fixed; + inset:0; + z-index:30; + display:flex; + align-items:center; + justify-content:center; + background:rgba(5,8,16,.58); + backdrop-filter:blur(2px); + transition:opacity .2s ease; + } + #responseWaitOverlay.is-hidden { + opacity:0; + pointer-events:none; + } + .response-wait-dialog { + display:flex; + align-items:center; + gap:10px; + padding:14px 18px; + border:1px solid rgba(255,255,255,.16); + border-radius:8px; + background:rgba(17,21,32,.94); + color:rgba(255,255,255,.9); + font:13px sans-serif; + font-weight:700; + box-shadow:0 18px 48px rgba(0,0,0,.3); + } + .response-wait-spinner { + width:16px; + height:16px; + border:2px solid rgba(255,255,255,.22); + border-top-color:#3b7ffa; + border-radius:50%; + animation:response-wait-spin .75s linear infinite; + } + @keyframes response-wait-spin { + to { transform:rotate(360deg); } + } #downloadWrap { position:relative; } #downloadMap, #pathToggle, + #poseToggle, #goalToggle, + #obstacleToggle, + #initToggle, #cameraPresetSelect { min-height:32px; border:1px solid rgba(255,255,255,.22); @@ -89,7 +138,10 @@ } #downloadMap, #pathToggle, - #goalToggle { + #poseToggle, + #goalToggle, + #obstacleToggle, + #initToggle { padding:0 11px; } #downloadMap { @@ -109,7 +161,9 @@ } #downloadMap:hover, #pathToggle:hover, + #poseToggle:hover, #goalToggle:hover, + #obstacleToggle:hover, #cameraPresetSelect:hover { background-color:rgba(17,24,39,.58); border-color:rgba(255,255,255,.34); @@ -119,6 +173,10 @@ opacity:.45; cursor:not-allowed; } + #goalToggle:disabled { + opacity:.42; + cursor:not-allowed; + } #pathToggle.active { background:rgba(37,99,235,.62); border-color:rgba(147,197,253,.55); @@ -129,6 +187,16 @@ border-color:rgba(134,239,172,.55); color:#fff; } + #poseToggle.active { + background:rgba(37,99,235,.62); + border-color:rgba(147,197,253,.55); + color:#fff; + } + #obstacleToggle.active { + background:rgba(217,119,6,.62); + border-color:rgba(253,230,138,.62); + color:#fff; + } #downloadMenu { position:absolute; right:0; @@ -154,24 +222,34 @@ font-weight:700; cursor:pointer; } - #downloadMenu button:hover { + #downloadMenu button:hover { background:rgba(255,255,255,.1); color:#fff; } + .editor-mode #topRightControls, + .editor-mode #miniMap, + .editor-mode #miniMapToggle, + .editor-mode #keyGuide { + display:none; + } + .nav2-slam #goalToggle, .nav2-slam #poseToggle { display:none; } + .nav2-navigation #downloadWrap { display:none; } + .nav2-navigation #topLeftControls { display:block; } + .real-runtime #topLeftControls { display:none; } +
+ +
- -
- - - -
+
+ +