decomposed functions.

This commit is contained in:
Michael Mainguy 2023-08-23 14:15:44 -05:00
parent d59e75ddc9
commit f44b2129c8
30 changed files with 576 additions and 486 deletions

View File

@ -49,6 +49,7 @@
<div id="graphContainer"></div> <div id="graphContainer"></div>
<div id="questLaunch"><a href="https://www.oculus.com/open_url/?url=https://www.deepdiagram.com/">Launch On Quest</a> <div id="questLaunch"><a href="https://www.oculus.com/open_url/?url=https://www.deepdiagram.com/">Launch On Quest</a>
</div> </div>
<input id="textInput" type="text"/>
<script type="module" src="./src/app.ts"></script> <script type="module" src="./src/app.ts"></script>
</body> </body>
</html> </html>

279
package-lock.json generated
View File

@ -8,16 +8,16 @@
"name": "immersive", "name": "immersive",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@babylonjs/core": "^6.15.0", "@babylonjs/core": "^6.17.1",
"@babylonjs/gui": "^6.15.0", "@babylonjs/gui": "^6.17.1",
"@babylonjs/havok": "1.1.1", "@babylonjs/havok": "1.1.4",
"@babylonjs/inspector": "^6.15.0", "@babylonjs/inspector": "^6.17.1",
"@babylonjs/loaders": "^6.15.0", "@babylonjs/loaders": "^6.17.1",
"@babylonjs/serializers": "^6.15.0", "@babylonjs/serializers": "^6.17.1",
"@cloudflare/workers-types": "^4.20230807.0", "@cloudflare/workers-types": "^4.20230821.0",
"@netlify/functions": "^1.6.0", "@netlify/functions": "^1.6.0",
"@typed-mxgraph/typed-mxgraph": "^1.0.8", "@typed-mxgraph/typed-mxgraph": "^1.0.8",
"@types/node": "^14.18.54", "@types/node": "^18.14.0",
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-observable": "^4.0.1-beta.13", "dexie-observable": "^4.0.1-beta.13",
"earcut": "^2.2.4", "earcut": "^2.2.4",
@ -34,7 +34,7 @@
}, },
"devDependencies": { "devDependencies": {
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^4.3.9", "vite": "^4.4.9",
"vite-plugin-api": "^0.1.11", "vite-plugin-api": "^0.1.11",
"vite-plugin-cp": "^1.0.0" "vite-plugin-cp": "^1.0.0"
} }
@ -51,14 +51,14 @@
} }
}, },
"node_modules/@babylonjs/core": { "node_modules/@babylonjs/core": {
"version": "6.15.0", "version": "6.17.1",
"resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-6.15.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-6.17.1.tgz",
"integrity": "sha512-eoeJ3RB6xYC63ZuGGuceF7rrVA1OFIlO3cvBvAxsoBIzxTSLxyhmG4wwktEvCAePxZ7W7CDYNtA061edGWhxUw==" "integrity": "sha512-CMhbyA7FEjYJC1JMetfRVH955lDwpKASufjeYw0UTB92+tlwwOsonN8eYr2r9DAHb+7UcQegGopx/nj+THAcIQ=="
}, },
"node_modules/@babylonjs/gui": { "node_modules/@babylonjs/gui": {
"version": "6.15.0", "version": "6.17.1",
"resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-6.15.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-6.17.1.tgz",
"integrity": "sha512-WkR/r8wLbKyzUuXUgcWVaTZO5drxQ8YjkstDRz/ZrhfOTIEFDpidd7onDhaQ9wmekQEpFHcKJejJ1/MLXYLwAg==", "integrity": "sha512-AQUE+r71X889I8hHg58Gpou7eeksIY878hrROnBbV2W8UpAAwL9p4A4kQ+EG8gTWwmn+NnahSRblmHfYnsT2KA==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^6.0.0" "@babylonjs/core": "^6.0.0"
} }
@ -76,17 +76,17 @@
} }
}, },
"node_modules/@babylonjs/havok": { "node_modules/@babylonjs/havok": {
"version": "1.1.1", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/@babylonjs/havok/-/havok-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/havok/-/havok-1.1.4.tgz",
"integrity": "sha512-QIygEnKPYYPCE8QuJDxDLYPMj+W5Yha6NOdUfpvcVfZwtjVDE+eOa2Y5el7muQD563OdeJS+Kzmhyg+5qAZHBA==", "integrity": "sha512-mK/sgqv4LaI4BjoQgWYGxOBX45hVauZ8PopPkIUIB42DiVPgWkiCZbBQ9pL7r1tbLhThvV1RTokj4z5bVGBayw==",
"dependencies": { "dependencies": {
"@types/emscripten": "^1.39.6" "@types/emscripten": "^1.39.6"
} }
}, },
"node_modules/@babylonjs/inspector": { "node_modules/@babylonjs/inspector": {
"version": "6.15.0", "version": "6.17.1",
"resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-6.15.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-6.17.1.tgz",
"integrity": "sha512-wN1jVC+gxQDcLL/dyuIMbedPZpxTHNW9gto82jvgyjXLIUKOWiQUVJS7moaLhTM27BMWBrHMfG+K4RnsnKEW9A==", "integrity": "sha512-WrztLKLQpbt4mFFR4xYDfsFrYORFfDH4pG7LjoeeOIANZhGspZ4Sk1HdNdQ2OoDDLZQpABdyZ9RLHKo/XycAjA==",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.1.0", "@fortawesome/fontawesome-svg-core": "^6.1.0",
"@fortawesome/free-regular-svg-icons": "^6.0.0", "@fortawesome/free-regular-svg-icons": "^6.0.0",
@ -104,9 +104,9 @@
} }
}, },
"node_modules/@babylonjs/loaders": { "node_modules/@babylonjs/loaders": {
"version": "6.15.0", "version": "6.17.1",
"resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-6.15.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-6.17.1.tgz",
"integrity": "sha512-pE22KVLEWcsWPmiL+TFsNyqLTMGhnt/6oPDy3nWpMwHTfjeaoW9qTV7hFDwhXopzU1Ddp6c/DhzFZalgSvCvbg==", "integrity": "sha512-k4g2rnqKnzoq+8AYO4IQL3aLAJDCCJrpL8Qj/CoVFjt3fDsPzC3ncnmu45VaTwpiXI5St/qfX3s9Bwncn6aI+A==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^6.0.0", "@babylonjs/core": "^6.0.0",
"babylonjs-gltf2interface": "^6.0.0" "babylonjs-gltf2interface": "^6.0.0"
@ -122,18 +122,18 @@
} }
}, },
"node_modules/@babylonjs/serializers": { "node_modules/@babylonjs/serializers": {
"version": "6.15.0", "version": "6.17.1",
"resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-6.15.0.tgz", "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-6.17.1.tgz",
"integrity": "sha512-qUKqMe18wlEQpyh5cAa/u/B4xMZ2tKh5K1CurnN9TXaM6i8wImRL4mmXqlwy/Tq18zUGmfmPyU1p1qPuD1ytcg==", "integrity": "sha512-+wSKhOPKu9wsAB4cmRARyYMgB7uGjr0axnFwZUBp8zaJ2beW9YxFvSqFcRVe2cgrwRel5FkVlM0xDxgak3dPVg==",
"peerDependencies": { "peerDependencies": {
"@babylonjs/core": "^6.0.0", "@babylonjs/core": "^6.0.0",
"babylonjs-gltf2interface": "^6.0.0" "babylonjs-gltf2interface": "^6.0.0"
} }
}, },
"node_modules/@cloudflare/workers-types": { "node_modules/@cloudflare/workers-types": {
"version": "4.20230807.0", "version": "4.20230821.0",
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20230807.0.tgz", "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20230821.0.tgz",
"integrity": "sha512-gQczWuGE2rxmpzOCNn0zLbx8Xz0gqspdE9S7tu4Xax39q1csgO/E9flcS+KG3GHB522ugOh84inmABDhpeJnvQ==" "integrity": "sha512-lVQSyr5E4CEkQw7WIdsrMTj+kHjsm28mJ0B5AhNFByKR+16KTFsU/RW/nGLKHHW2jxT5lvYI+HjNQMzC9QR8Ng=="
}, },
"node_modules/@eneris/push-receiver": { "node_modules/@eneris/push-receiver": {
"version": "3.1.4", "version": "3.1.4",
@ -150,9 +150,9 @@
} }
}, },
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
"integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -166,9 +166,9 @@
} }
}, },
"node_modules/@esbuild/android-arm64": { "node_modules/@esbuild/android-arm64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
"integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -182,9 +182,9 @@
} }
}, },
"node_modules/@esbuild/android-x64": { "node_modules/@esbuild/android-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
"integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -198,9 +198,9 @@
} }
}, },
"node_modules/@esbuild/darwin-arm64": { "node_modules/@esbuild/darwin-arm64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
"integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -214,9 +214,9 @@
} }
}, },
"node_modules/@esbuild/darwin-x64": { "node_modules/@esbuild/darwin-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
"integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -230,9 +230,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-arm64": { "node_modules/@esbuild/freebsd-arm64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
"integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -246,9 +246,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-x64": { "node_modules/@esbuild/freebsd-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
"integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -262,9 +262,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm": { "node_modules/@esbuild/linux-arm": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
"integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -278,9 +278,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm64": { "node_modules/@esbuild/linux-arm64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
"integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -294,9 +294,9 @@
} }
}, },
"node_modules/@esbuild/linux-ia32": { "node_modules/@esbuild/linux-ia32": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
"integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -310,9 +310,9 @@
} }
}, },
"node_modules/@esbuild/linux-loong64": { "node_modules/@esbuild/linux-loong64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
"integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@ -326,9 +326,9 @@
} }
}, },
"node_modules/@esbuild/linux-mips64el": { "node_modules/@esbuild/linux-mips64el": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
"integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
@ -342,9 +342,9 @@
} }
}, },
"node_modules/@esbuild/linux-ppc64": { "node_modules/@esbuild/linux-ppc64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
"integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -358,9 +358,9 @@
} }
}, },
"node_modules/@esbuild/linux-riscv64": { "node_modules/@esbuild/linux-riscv64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
"integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@ -374,9 +374,9 @@
} }
}, },
"node_modules/@esbuild/linux-s390x": { "node_modules/@esbuild/linux-s390x": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
"integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@ -390,9 +390,9 @@
} }
}, },
"node_modules/@esbuild/linux-x64": { "node_modules/@esbuild/linux-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
"integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -406,9 +406,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-x64": { "node_modules/@esbuild/netbsd-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
"integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -422,9 +422,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-x64": { "node_modules/@esbuild/openbsd-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
"integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -438,9 +438,9 @@
} }
}, },
"node_modules/@esbuild/sunos-x64": { "node_modules/@esbuild/sunos-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
"integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -454,9 +454,9 @@
} }
}, },
"node_modules/@esbuild/win32-arm64": { "node_modules/@esbuild/win32-arm64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
"integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -470,9 +470,9 @@
} }
}, },
"node_modules/@esbuild/win32-ia32": { "node_modules/@esbuild/win32-ia32": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
"integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -486,9 +486,9 @@
} }
}, },
"node_modules/@esbuild/win32-x64": { "node_modules/@esbuild/win32-x64": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
"integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -983,9 +983,9 @@
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "14.18.54", "version": "18.17.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.8.tgz",
"integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==" "integrity": "sha512-Av/7MqX/iNKwT9Tr60V85NqMnsmh8ilfJoBlIVibkXfitk9Q22D9Y5mSpm+FvG5DET7EbVfB40bOiLzKgYFgPw=="
}, },
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
@ -1810,9 +1810,9 @@
} }
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.17.19", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
"integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
@ -1822,28 +1822,28 @@
"node": ">=12" "node": ">=12"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/android-arm": "0.17.19", "@esbuild/android-arm": "0.18.20",
"@esbuild/android-arm64": "0.17.19", "@esbuild/android-arm64": "0.18.20",
"@esbuild/android-x64": "0.17.19", "@esbuild/android-x64": "0.18.20",
"@esbuild/darwin-arm64": "0.17.19", "@esbuild/darwin-arm64": "0.18.20",
"@esbuild/darwin-x64": "0.17.19", "@esbuild/darwin-x64": "0.18.20",
"@esbuild/freebsd-arm64": "0.17.19", "@esbuild/freebsd-arm64": "0.18.20",
"@esbuild/freebsd-x64": "0.17.19", "@esbuild/freebsd-x64": "0.18.20",
"@esbuild/linux-arm": "0.17.19", "@esbuild/linux-arm": "0.18.20",
"@esbuild/linux-arm64": "0.17.19", "@esbuild/linux-arm64": "0.18.20",
"@esbuild/linux-ia32": "0.17.19", "@esbuild/linux-ia32": "0.18.20",
"@esbuild/linux-loong64": "0.17.19", "@esbuild/linux-loong64": "0.18.20",
"@esbuild/linux-mips64el": "0.17.19", "@esbuild/linux-mips64el": "0.18.20",
"@esbuild/linux-ppc64": "0.17.19", "@esbuild/linux-ppc64": "0.18.20",
"@esbuild/linux-riscv64": "0.17.19", "@esbuild/linux-riscv64": "0.18.20",
"@esbuild/linux-s390x": "0.17.19", "@esbuild/linux-s390x": "0.18.20",
"@esbuild/linux-x64": "0.17.19", "@esbuild/linux-x64": "0.18.20",
"@esbuild/netbsd-x64": "0.17.19", "@esbuild/netbsd-x64": "0.18.20",
"@esbuild/openbsd-x64": "0.17.19", "@esbuild/openbsd-x64": "0.18.20",
"@esbuild/sunos-x64": "0.17.19", "@esbuild/sunos-x64": "0.18.20",
"@esbuild/win32-arm64": "0.17.19", "@esbuild/win32-arm64": "0.18.20",
"@esbuild/win32-ia32": "0.17.19", "@esbuild/win32-ia32": "0.18.20",
"@esbuild/win32-x64": "0.17.19" "@esbuild/win32-x64": "0.18.20"
} }
}, },
"node_modules/escalade": { "node_modules/escalade": {
@ -3141,9 +3141,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.24", "version": "8.4.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
"integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -3424,9 +3424,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "3.25.1", "version": "3.28.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
"integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==", "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==",
"dev": true, "dev": true,
"bin": { "bin": {
"rollup": "dist/bin/rollup" "rollup": "dist/bin/rollup"
@ -3929,14 +3929,14 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "4.3.9", "version": "4.4.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
"integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"esbuild": "^0.17.5", "esbuild": "^0.18.10",
"postcss": "^8.4.23", "postcss": "^8.4.27",
"rollup": "^3.21.0" "rollup": "^3.27.1"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
@ -3944,12 +3944,16 @@
"engines": { "engines": {
"node": "^14.18.0 || >=16.0.0" "node": "^14.18.0 || >=16.0.0"
}, },
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": { "optionalDependencies": {
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@types/node": ">= 14", "@types/node": ">= 14",
"less": "*", "less": "*",
"lightningcss": "^1.21.0",
"sass": "*", "sass": "*",
"stylus": "*", "stylus": "*",
"sugarss": "*", "sugarss": "*",
@ -3962,6 +3966,9 @@
"less": { "less": {
"optional": true "optional": true
}, },
"lightningcss": {
"optional": true
},
"sass": { "sass": {
"optional": true "optional": true
}, },

View File

@ -3,6 +3,9 @@
"private": true, "private": true,
"version": "0.0.1", "version": "0.0.1",
"type": "module", "type": "module",
"engines": {
"node": ">=18.0.0"
},
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
@ -12,16 +15,16 @@
"havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps" "havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps"
}, },
"dependencies": { "dependencies": {
"@babylonjs/core": "^6.15.0", "@babylonjs/core": "^6.17.1",
"@babylonjs/gui": "^6.15.0", "@babylonjs/gui": "^6.17.1",
"@babylonjs/havok": "1.1.1", "@babylonjs/havok": "1.1.4",
"@babylonjs/inspector": "^6.15.0", "@babylonjs/inspector": "^6.17.1",
"@babylonjs/loaders": "^6.15.0", "@babylonjs/loaders": "^6.17.1",
"@babylonjs/serializers": "^6.15.0", "@babylonjs/serializers": "^6.17.1",
"@cloudflare/workers-types": "^4.20230807.0", "@cloudflare/workers-types": "^4.20230821.0",
"@netlify/functions": "^1.6.0", "@netlify/functions": "^1.6.0",
"@typed-mxgraph/typed-mxgraph": "^1.0.8", "@typed-mxgraph/typed-mxgraph": "^1.0.8",
"@types/node": "^14.18.54", "@types/node": "^18.14.0",
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-observable": "^4.0.1-beta.13", "dexie-observable": "^4.0.1-beta.13",
"earcut": "^2.2.4", "earcut": "^2.2.4",
@ -38,7 +41,7 @@
}, },
"devDependencies": { "devDependencies": {
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^4.3.9", "vite": "^4.4.9",
"vite-plugin-api": "^0.1.11", "vite-plugin-api": "^0.1.11",
"vite-plugin-cp": "^1.0.0" "vite-plugin-cp": "^1.0.0"
} }

View File

@ -82,7 +82,14 @@ export class App {
} }
}); });
xr.baseExperience.sessionManager.onXRSessionInit.add((session) => {
session.addEventListener('visibilitychange', (ev) => {
console.log(ev);
});
});
xr.baseExperience.onStateChangedObservable.add((state) => { xr.baseExperience.onStateChangedObservable.add((state) => {
console.log(state);
if (state == WebXRState.IN_XR) { if (state == WebXRState.IN_XR) {
scene.audioEnabled = true; scene.audioEnabled = true;
xr.baseExperience.camera.position = new Vector3(0, 1.6, 0); xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
@ -93,8 +100,10 @@ export class App {
}); });
} }
}); });
const rig = new Rigplatform(scene, xr, diagramManager, controllers); const rig = new Rigplatform(scene, xr, diagramManager, controllers);

View File

@ -12,10 +12,12 @@ import {
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity"; import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
import log from "loglevel"; import log from "loglevel";
import {Controllers} from "./controllers"; import {ControllerEventType, Controllers} from "./controllers";
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity"; import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
import {setupTransformNode} from "./functions/setupTransformNode"; import {setupTransformNode} from "./functions/setupTransformNode";
import {reparent} from "./functions/reparent"; import {reparent} from "./functions/reparent";
import {snapGridVal} from "../util/functions/snapGridVal";
import {snapRotateVal} from "../util/functions/snapRotateVal";
export class Base { export class Base {
static stickVector = Vector3.Zero(); static stickVector = Vector3.Zero();
@ -72,26 +74,35 @@ export class Base {
} }
}, -1, false, this); }, -1, false, this);
this.controllers.controllerObserver.add((event) => { this.controllers.controllerObserver.add((event) => {
if (event.type == 'pulse') {
this.logger.debug(event); this.logger.debug(event);
switch (event.type) {
case ControllerEventType.PULSE:
if (event.gripId == this?.controller?.grip?.id) { if (event.gripId == this?.controller?.grip?.id) {
this.controller?.motionController?.pulse(.25, 30) this.controller?.motionController?.pulse(.25, 30)
.then(() => { .then(() => {
this.logger.debug("pulse done"); this.logger.debug("pulse done");
}); });
} }
;
break;
case ControllerEventType.HIDE:
this.disable();
break;
case ControllerEventType.SHOW:
this.enable();
break;
} }
}); });
} }
public disable() { public disable() {
this.controller.motionController.rootMesh.setEnabled(false); this.controller.motionController.rootMesh.setEnabled(false)
this.controller.pointer.setEnabled(false); this.controller.pointer.setEnabled(false);
} }
public enable() { public enable() {
this.controller.motionController.rootMesh.setEnabled(true); this.controller.motionController.rootMesh.setEnabled(true);
this.controller.pointer.setEnabled(true); this.controller.pointer.setEnabled(true)
} }
private grab() { private grab() {
@ -174,8 +185,8 @@ export class Base {
this.grabbedMeshParentId = null; this.grabbedMeshParentId = null;
if (!mesh.physicsBody) { if (!mesh.physicsBody) {
mesh.position = this.diagramManager.config.snapGridVal(mesh.position, this.diagramManager.config.current.gridSnap); mesh.position = snapGridVal(mesh.position, this.diagramManager.config.current.gridSnap);
mesh.rotation = this.diagramManager.config.snapRotateVal(mesh.rotation, this.diagramManager.config.current.rotateSnap); mesh.rotation = snapRotateVal(mesh.rotation, this.diagramManager.config.current.rotateSnap);
} }
this.previousParentId = null; this.previousParentId = null;
this.previousScaling = null; this.previousScaling = null;

View File

@ -1,11 +1,34 @@
import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core"; import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
export type ControllerEventType = { export type ControllerEvent = {
type: string, type: ControllerEventType,
value?: number, value?: number,
gripId?: string; gripId?: string;
} }
export enum ControllerEventType {
GRIP = 'grip',
HIDE = 'hide',
SHOW = 'show',
PULSE = 'pulse',
SQUEEZE = 'squeeze',
Y_BUTTON = 'y-button',
X_BUTTON = 'x-button',
A_BUTTON = 'a-button',
B_BUTTON = 'b-button',
THUMBSTICK = 'thumbstick',
THUMBSTICK_CHANGED = 'thumbstickChanged',
DECREASE_VELOCITY = 'decreaseVelocity',
INCREASE_VELOCITY = 'decreaseVelocity',
LEFT_RIGHT = 'leftright',
FORWARD_BACK = 'forwardback',
TURN = 'turn',
UP_DOWN = 'updown',
TRIGGER = 'trigger',
MENU = 'menu'
}
export class Controllers { export class Controllers {
public movable: TransformNode | AbstractMesh; public movable: TransformNode | AbstractMesh;
public readonly controllerObserver: Observable<ControllerEventType> = new Observable(); public readonly controllerObserver: Observable<ControllerEvent> = new Observable();
} }

View File

@ -1,6 +1,6 @@
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core"; import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Base} from "./base"; import {Base} from "./base";
import {Controllers} from "./controllers"; import {ControllerEventType, Controllers} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {ConfigMenu} from "../menus/configMenu"; import {ConfigMenu} from "../menus/configMenu";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
@ -13,7 +13,7 @@ export class Left extends Base {
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) { WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
super(controller, scene, xr, controllers, diagramManager); super(controller, scene, xr, controllers, diagramManager);
this.configMenu = new ConfigMenu(this.scene, xr.baseExperience, this.controllers, this.diagramManager.config); this.configMenu = new ConfigMenu(this.scene, xr, this.controllers, this.diagramManager.config);
this.controller.onMotionControllerInitObservable.add((init) => { this.controller.onMotionControllerInitObservable.add((init) => {
if (init.components['xr-standard-thumbstick']) { if (init.components['xr-standard-thumbstick']) {
init.components['xr-standard-thumbstick'] init.components['xr-standard-thumbstick']
@ -31,7 +31,7 @@ export class Left extends Base {
if (value.pressed) { if (value.pressed) {
log.trace('Left', 'thumbstick changed'); log.trace('Left', 'thumbstick changed');
this.controllers.controllerObserver.notifyObservers({ this.controllers.controllerObserver.notifyObservers({
type: 'decreaseVelocity', type: ControllerEventType.DECREASE_VELOCITY,
value: value.value value: value.value
}); });
} }
@ -44,7 +44,10 @@ export class Left extends Base {
if (xbutton) { if (xbutton) {
xbutton.onButtonStateChangedObservable.add((button) => { xbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.controllers.controllerObserver.notifyObservers({type: 'x-button', value: button.value}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.X_BUTTON,
value: button.value
});
} }
}); });
} }
@ -54,7 +57,10 @@ export class Left extends Base {
if (ybutton) { if (ybutton) {
ybutton.onButtonStateChangedObservable.add((button) => { ybutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.controllers.controllerObserver.notifyObservers({type: 'y-button', value: button.value}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.Y_BUTTON,
value: button.value
});
} }
}); });
} }
@ -75,14 +81,17 @@ export class Left extends Base {
private moveRig(value: { x: number, y: number }) { private moveRig(value: { x: number, y: number }) {
if (Math.abs(value.x) > .1) { if (Math.abs(value.x) > .1) {
this.controllers.controllerObserver.notifyObservers({type: 'leftright', value: value.x * this.speedFactor}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.LEFT_RIGHT,
value: value.x * this.speedFactor
});
Base.stickVector.x = 1; Base.stickVector.x = 1;
} else { } else {
Base.stickVector.x = 0; Base.stickVector.x = 0;
} }
if (Math.abs(value.y) > .1) { if (Math.abs(value.y) > .1) {
this.controllers.controllerObserver.notifyObservers({ this.controllers.controllerObserver.notifyObservers({
type: 'forwardback', type: ControllerEventType.FORWARD_BACK,
value: value.y * this.speedFactor value: value.y * this.speedFactor
}); });
Base.stickVector.y = 1; Base.stickVector.y = 1;
@ -91,8 +100,8 @@ export class Left extends Base {
} }
if (Base.stickVector.equals(Vector3.Zero())) { if (Base.stickVector.equals(Vector3.Zero())) {
this.controllers.controllerObserver.notifyObservers({type: 'leftright', value: 0}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.LEFT_RIGHT, value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'forwardback', value: 0}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.FORWARD_BACK, value: 0});
} else { } else {
} }

View File

@ -1,6 +1,6 @@
import {Base} from "./base"; import {Base} from "./base";
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core"; import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Controllers} from "./controllers"; import {ControllerEventType, Controllers} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
@ -21,7 +21,10 @@ export class Right extends Base {
if (bbutton) { if (bbutton) {
bbutton.onButtonStateChangedObservable.add((button) => { bbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.controllers.controllerObserver.notifyObservers({type: 'b-button', value: button.value}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.B_BUTTON,
value: button.value
});
} }
}); });
} }
@ -33,7 +36,10 @@ export class Right extends Base {
.onButtonStateChangedObservable .onButtonStateChangedObservable
.add((button) => { .add((button) => {
if (button.pressed) { if (button.pressed) {
this.controllers.controllerObserver.notifyObservers({type: 'trigger', value: button.value}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.TRIGGER,
value: button.value
});
} }
}); });
} }
@ -44,7 +50,7 @@ export class Right extends Base {
abutton.onButtonStateChangedObservable.add((value) => { abutton.onButtonStateChangedObservable.add((value) => {
if (value.pressed) { if (value.pressed) {
log.getLogger("right").debug("a-button pressed"); log.getLogger("right").debug("a-button pressed");
this.controllers.controllerObserver.notifyObservers({type: 'menu'}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.MENU});
} }
}); });
} }
@ -59,7 +65,10 @@ export class Right extends Base {
thumbstick.onButtonStateChangedObservable.add((value) => { thumbstick.onButtonStateChangedObservable.add((value) => {
if (value.pressed) { if (value.pressed) {
log.trace('Right', `thumbstick changed ${value.value}`); log.trace('Right', `thumbstick changed ${value.value}`);
this.controllers.controllerObserver.notifyObservers({type: 'increaseVelocity', value: value.value}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.INCREASE_VELOCITY,
value: value.value
});
} }
}); });
} }
@ -67,19 +76,22 @@ export class Right extends Base {
private moveRig(value) { private moveRig(value) {
if (Math.abs(value.x) > .1) { if (Math.abs(value.x) > .1) {
this.controllers.controllerObserver.notifyObservers({type: 'turn', value: value.x}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.TURN, value: value.x});
} else { } else {
this.controllers.controllerObserver.notifyObservers({type: 'turn', value: 0}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.TURN, value: 0});
} }
if (Math.abs(value.y) > .1) { if (Math.abs(value.y) > .1) {
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: value.y * this.speedFactor}); this.controllers.controllerObserver.notifyObservers({
type: ControllerEventType.UP_DOWN,
value: value.y * this.speedFactor
});
Base.stickVector.z = 1; Base.stickVector.z = 1;
} else { } else {
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: 0}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0});
Base.stickVector.z = 0; Base.stickVector.z = 0;
} }
if (Base.stickVector.equals(Vector3.Zero())) { if (Base.stickVector.equals(Vector3.Zero())) {
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: 0}); this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0});
} }
} }
} }

View File

@ -17,7 +17,7 @@ import {
import {Right} from "./right"; import {Right} from "./right";
import {Left} from "./left"; import {Left} from "./left";
import {EditMenu} from "../menus/editMenu"; import {EditMenu} from "../menus/editMenu";
import {Controllers} from "./controllers"; import {ControllerEvent, ControllerEventType, Controllers} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
@ -90,7 +90,7 @@ export class Rigplatform {
this.controllers = controllers; this.controllers = controllers;
Rigplatform.xr = xr; Rigplatform.xr = xr;
Rigplatform.instance = this; Rigplatform.instance = this;
this.bMenu = new EditMenu(scene, xr, this.diagramManager); this.bMenu = new EditMenu(scene, xr, this.diagramManager, controllers);
this.camera = scene.activeCamera; this.camera = scene.activeCamera;
this.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene); this.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene);
@ -125,38 +125,35 @@ export class Rigplatform {
private registerObserver() { private registerObserver() {
if (!this.registered) { if (!this.registered) {
this.registered = true; this.registered = true;
this.controllers.controllerObserver.add((event: { type: string, value: number }) => { this.controllers.controllerObserver.add((event: ControllerEvent) => {
switch (event.type) { switch (event.type) {
case "increaseVelocity": case ControllerEventType.INCREASE_VELOCITY:
if (this.velocityIndex < this.velocityArray.length - 1) { if (this.velocityIndex < this.velocityArray.length - 1) {
this.velocityIndex++; this.velocityIndex++;
} else { } else {
this.velocityIndex = 0; this.velocityIndex = 0;
} }
break; break;
case "decreaseVelocity": case ControllerEventType.DECREASE_VELOCITY:
if (this.velocityIndex > 0) { if (this.velocityIndex > 0) {
this.velocityIndex--; this.velocityIndex--;
} else { } else {
this.velocityIndex = this.velocityArray.length - 1; this.velocityIndex = this.velocityArray.length - 1;
} }
break; break;
case "turn": case ControllerEventType.TURN:
this.turn(event.value); this.turn(event.value);
break; break;
case "forwardback": case ControllerEventType.FORWARD_BACK:
this.forwardback(event.value); this.forwardback(event.value);
break; break;
case "leftright": case ControllerEventType.LEFT_RIGHT:
this.leftright(event.value); this.leftright(event.value);
break; break;
case "updown": case ControllerEventType.UP_DOWN:
this.updown(event.value); this.updown(event.value);
break; break;
case "stop": case ControllerEventType.MENU:
log.warn("Rigplatform", "stop is no longer implemented");
break;
case "menu":
this.bMenu.toggle(); this.bMenu.toggle();
break; break;
} }

View File

@ -1,6 +1,6 @@
import {ActionManager, ExecuteCodeAction, PlaySoundAction, Scene} from "@babylonjs/core"; import {ActionManager, ExecuteCodeAction, PlaySoundAction, Scene} from "@babylonjs/core";
import {DiaSounds} from "../util/diaSounds"; import {DiaSounds} from "../util/diaSounds";
import {Controllers} from "../controllers/controllers"; import {ControllerEventType, Controllers} from "../controllers/controllers";
import log from "loglevel"; import log from "loglevel";
export class DiagramEntityActionManager { export class DiagramEntityActionManager {
@ -14,7 +14,7 @@ export class DiagramEntityActionManager {
this._actionManager.registerAction( this._actionManager.registerAction(
new ExecuteCodeAction(ActionManager.OnPointerOverTrigger, (evt) => { new ExecuteCodeAction(ActionManager.OnPointerOverTrigger, (evt) => {
controllers.controllerObserver.notifyObservers({ controllers.controllerObserver.notifyObservers({
type: 'pulse', type: ControllerEventType.PULSE,
gripId: evt?.additionalData?.pickResult?.gripTransform?.id gripId: evt?.additionalData?.pickResult?.gripTransform?.id
}) })
this.logger.debug(evt); this.logger.debug(evt);

View File

@ -9,7 +9,7 @@ import {Toolbox} from "../toolbox/toolbox";
import {PresentationManager} from "./presentationManager"; import {PresentationManager} from "./presentationManager";
import {DiagramEntityActionManager} from "./diagramEntityActionManager"; import {DiagramEntityActionManager} from "./diagramEntityActionManager";
import {diagramEventHandler} from "./diagramEventHandler"; import {diagramEventHandler} from "./diagramEventHandler";
import {deepCopy} from "../util/deepCopy"; import {deepCopy} from "../util/functions/deepCopy";
import {applyPhysics} from "./functions/diagramShapePhysics"; import {applyPhysics} from "./functions/diagramShapePhysics";
import {applyScaling} from "./functions/applyScaling"; import {applyScaling} from "./functions/applyScaling";
import {toDiagramEntity} from "./functions/toDiagramEntity"; import {toDiagramEntity} from "./functions/toDiagramEntity";

View File

@ -1,6 +1,7 @@
import {Observable, Scene, WebXRDefaultExperience} from "@babylonjs/core"; import {Observable, Scene, WebXRDefaultExperience} from "@babylonjs/core";
import log from "loglevel"; import log from "loglevel";
import {AdvancedDynamicTexture, InputText} from "@babylonjs/gui"; import {AdvancedDynamicTexture, InputText} from "@babylonjs/gui";
import {ControllerEventType, Controllers} from "../controllers/controllers";
export type TextEvent = { export type TextEvent = {
text: string; text: string;
@ -9,12 +10,14 @@ export type InputTextViewOptions = {
scene?: Scene; scene?: Scene;
xr?: WebXRDefaultExperience; xr?: WebXRDefaultExperience;
text?: string; text?: string;
controllers?: Controllers;
} }
export class InputTextView { export class InputTextView {
public readonly onTextObservable: Observable<TextEvent> = new Observable<TextEvent>(); public readonly onTextObservable: Observable<TextEvent> = new Observable<TextEvent>();
private readonly text: string; private readonly text: string;
private readonly scene: Scene; private readonly scene: Scene;
private readonly controllers: Controllers;
private readonly xr: WebXRDefaultExperience; private readonly xr: WebXRDefaultExperience;
constructor(options: InputTextViewOptions) { constructor(options: InputTextViewOptions) {
@ -27,10 +30,14 @@ export class InputTextView {
if (options.scene) { if (options.scene) {
this.scene = options.scene; this.scene = options.scene;
} }
if (options.controllers) {
this.controllers = options.controllers;
}
} }
public show() { public show() {
if (this?.xr?.baseExperience?.sessionManager?.inXRSession) {
if ((this.xr as WebXRDefaultExperience).baseExperience?.sessionManager?.inXRSession) {
this.showXr(); this.showXr();
} else { } else {
this.showWeb(); this.showWeb();
@ -62,33 +69,31 @@ export class InputTextView {
textInput.type = "text"; textInput.type = "text";
document.body.appendChild(textInput); document.body.appendChild(textInput);
textInput.value = this.text; textInput.value = this.text;
if (this.xr?.baseExperience?.sessionManager?.inXRSession) { this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.HIDE});
/*if (this.xr?.baseExperience?.sessionManager?.inXRSession) {
this.xr.input.controllers.forEach((controller) => { this.xr.input.controllers.forEach((controller) => {
controller.motionController.rootMesh.setEnabled(false); controller.motionController.rootMesh.setEnabled(false);
controller.pointer.setEnabled(false); controller.pointer.setEnabled(false);
}); });
} }*/
textInput.focus();
if (navigator.userAgent.indexOf('Macintosh') > -1) {
textInput.addEventListener('input', (event) => {
log.debug(event);
});
} else {
textInput.addEventListener('blur', () => { textInput.addEventListener('blur', () => {
log.getLogger('bmenu').debug("blur"); log.getLogger('bmenu').debug("blur");
this.onTextObservable.notifyObservers({text: textInput.value}); this.onTextObservable.notifyObservers({text: textInput.value});
if (this.xr?.baseExperience?.sessionManager?.inXRSession) { this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.SHOW});
/*if (this.xr?.baseExperience?.sessionManager?.inXRSession) {
this.xr.input.controllers.forEach((controller) => { this.xr.input.controllers.forEach((controller) => {
controller.motionController.rootMesh.setEnabled(true); controller.motionController.rootMesh.setEnabled(true);
controller.pointer.setEnabled(true); controller.pointer.setEnabled(true);
}); });
} }*/
textInput.blur(); textInput.blur();
textInput.remove(); textInput.remove();
}); });
}
textInput.focus();
} }
} }

View File

@ -1,12 +1,12 @@
import {Scene, WebXRExperienceHelper} from "@babylonjs/core"; import {Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {Controllers} from "../controllers/controllers"; import {Controllers} from "../controllers/controllers";
export class AbstractMenu { export class AbstractMenu {
protected scene: Scene; protected scene: Scene;
protected xr: WebXRExperienceHelper; protected xr: WebXRDefaultExperience;
protected controllers: Controllers; protected controllers: Controllers;
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) { constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
this.scene = scene; this.scene = scene;
this.xr = xr; this.xr = xr;
this.controllers = controllers; this.controllers = controllers;

View File

@ -1,11 +1,11 @@
import {AdvancedDynamicTexture, RadioGroup, SelectionPanel} from "@babylonjs/gui"; import {AdvancedDynamicTexture, RadioGroup, SelectionPanel} from "@babylonjs/gui";
import {AbstractMesh, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core"; import {AbstractMesh, MeshBuilder, Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {CameraHelper} from "../util/cameraHelper";
import log from "loglevel"; import log from "loglevel";
import {AppConfig} from "../util/appConfig"; import {AppConfig} from "../util/appConfig";
import {Controllers} from "../controllers/controllers"; import {ControllerEventType, Controllers} from "../controllers/controllers";
import {DiaSounds} from "../util/diaSounds"; import {DiaSounds} from "../util/diaSounds";
import {AbstractMenu} from "./abstractMenu"; import {AbstractMenu} from "./abstractMenu";
import {setMenuPosition} from "../util/functions/setMenuPosition";
export class ConfigMenu extends AbstractMenu { export class ConfigMenu extends AbstractMenu {
private sounds: DiaSounds; private sounds: DiaSounds;
@ -21,6 +21,28 @@ export class ConfigMenu extends AbstractMenu {
{label: "1", value: 1}, {label: "1", value: 1},
] ]
private rotationSnaps: Array<{ label: string, value: number }> = [
{label: "Off", value: 0},
{label: "22.5", value: 22.5},
{label: "45", value: 45},
{label: "90", value: 90},
]
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers, config: AppConfig) {
super(scene, xr, controllers);
this.config = config;
this.sounds = new DiaSounds(scene);
if (!this.yObserver) {
this.controllers.controllerObserver.add((event) => {
if (event.type == ControllerEventType.Y_BUTTON) {
this.toggle();
}
});
}
}
public toggle() { public toggle() {
if (this.configPlane) { if (this.configPlane) {
this.sounds.exit.play(); this.sounds.exit.play();
@ -48,28 +70,7 @@ export class ConfigMenu extends AbstractMenu {
this.buildRotationSnapControl(selectionPanel); this.buildRotationSnapControl(selectionPanel);
this.buildTurnSnapControl(selectionPanel); this.buildTurnSnapControl(selectionPanel);
CameraHelper.setMenuPosition(this.configPlane, this.scene); setMenuPosition(this.configPlane, this.scene);
}
private rotationSnaps: Array<{ label: string, value: number }> = [
{label: "Off", value: 0},
{label: "22.5", value: 22.5},
{label: "45", value: 45},
{label: "90", value: 90},
]
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers, config: AppConfig) {
super(scene, xr, controllers);
this.config = config;
this.sounds = new DiaSounds(scene);
if (!this.yObserver) {
this.controllers.controllerObserver.add((event) => {
if (event.type == 'y-button') {
this.toggle();
}
});
}
} }
private buildCreateScaleControl(selectionPanel: SelectionPanel): RadioGroup { private buildCreateScaleControl(selectionPanel: SelectionPanel): RadioGroup {

View File

@ -9,7 +9,7 @@ import {
Scene, Scene,
StandardMaterial, StandardMaterial,
Vector3, Vector3,
WebXRDefaultExperience WebXRDefaultExperience,
} from "@babylonjs/core"; } from "@babylonjs/core";
import {Button3D, GUI3DManager, PlanePanel, TextBlock} from "@babylonjs/gui"; import {Button3D, GUI3DManager, PlanePanel, TextBlock} from "@babylonjs/gui";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
@ -18,20 +18,20 @@ import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
import log from "loglevel"; import log from "loglevel";
import {InputTextView} from "../information/inputTextView"; import {InputTextView} from "../information/inputTextView";
import {DiaSounds} from "../util/diaSounds"; import {DiaSounds} from "../util/diaSounds";
import {CameraHelper} from "../util/cameraHelper";
import {TextLabel} from "../diagram/textLabel"; import {TextLabel} from "../diagram/textLabel";
import {DiagramConnection} from "../diagram/diagramConnection"; import {DiagramConnection} from "../diagram/diagramConnection";
import {GLTF2Export} from "@babylonjs/serializers"; import {GLTF2Export} from "@babylonjs/serializers";
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity"; import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
import {AbstractMenu} from "./abstractMenu";
import {Controllers} from "../controllers/controllers";
import {setMenuPosition} from "../util/functions/setMenuPosition";
export class EditMenu { export class EditMenu extends AbstractMenu {
private state: EditMenuState = EditMenuState.NONE; private state: EditMenuState = EditMenuState.NONE;
private manager: GUI3DManager; private manager: GUI3DManager;
private readonly scene: Scene;
private paintColor: string = null; private paintColor: string = null;
private readonly logger: log.Logger = log.getLogger('EditMenu'); private readonly logger: log.Logger = log.getLogger('EditMenu');
private gizmoManager: GizmoManager; private gizmoManager: GizmoManager;
private readonly xr: WebXRDefaultExperience;
private readonly diagramManager: DiagramManager; private readonly diagramManager: DiagramManager;
private connection: DiagramConnection = null; private connection: DiagramConnection = null;
private panel: PlanePanel; private panel: PlanePanel;
@ -49,9 +49,9 @@ export class EditMenu {
}); });
} }
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager) { constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
super(scene, xr, controllers);
this.scene = scene; this.scene = scene;
this.xr = xr;
this.sounds = new DiaSounds(scene); this.sounds = new DiaSounds(scene);
this.diagramManager = diagramManager; this.diagramManager = diagramManager;
this.gizmoManager = new GizmoManager(scene); this.gizmoManager = new GizmoManager(scene);
@ -129,7 +129,7 @@ export class EditMenu {
} else { } else {
this.sounds.enter.play(); this.sounds.enter.play();
CameraHelper.setMenuPosition(this.manager.rootContainer.children[0].node, this.scene); setMenuPosition(this.manager.rootContainer.children[0].node, this.scene);
this.isVisible = true; this.isVisible = true;
} }
} }
@ -251,13 +251,15 @@ export class EditMenu {
if (mesh?.metadata?.text) { if (mesh?.metadata?.text) {
text = mesh.metadata.text; text = mesh.metadata.text;
} }
const textInput = new InputTextView({xr: this.xr, text: text}); const textInput = new InputTextView({xr: this.xr, text: text, controllers: this.controllers});
textInput.show(); textInput.show();
textInput.onTextObservable.addOnce((value) => { textInput.onTextObservable.addOnce((value) => {
this.persist(mesh, value.text); this.persist(mesh, value.text);
TextLabel.updateTextNode(mesh, value.text); TextLabel.updateTextNode(mesh, value.text);
}); });
} }
private showNewRelic() { private showNewRelic() {

View File

@ -1,13 +1,13 @@
import {AbstractMesh, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core"; import {AbstractMesh, MeshBuilder, Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {Controllers} from "../controllers/controllers"; import {Controllers} from "../controllers/controllers";
import {AbstractMenu} from "./abstractMenu"; import {AbstractMenu} from "./abstractMenu";
import {AdvancedDynamicTexture, Grid, TextBlock} from "@babylonjs/gui"; import {AdvancedDynamicTexture, Grid, TextBlock} from "@babylonjs/gui";
import {CameraHelper} from "../util/cameraHelper"; import {setMenuPosition} from "../util/functions/setMenuPosition";
export class IntegrationMenu extends AbstractMenu { export class IntegrationMenu extends AbstractMenu {
private plane: AbstractMesh = null; private plane: AbstractMesh = null;
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) { constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
super(scene, xr, controllers); super(scene, xr, controllers);
this.buildMenu(); this.buildMenu();
} }
@ -28,7 +28,7 @@ export class IntegrationMenu extends AbstractMenu {
grid.addControl(labelText1, 0, 0); grid.addControl(labelText1, 0, 0);
const labelText2 = new TextBlock("labelText1", "New Relic Account"); const labelText2 = new TextBlock("labelText1", "New Relic Account");
grid.addControl(labelText2, 1, 0); grid.addControl(labelText2, 1, 0);
CameraHelper.setMenuPosition(this.plane, this.scene); setMenuPosition(this.plane, this.scene);
} }

View File

@ -0,0 +1,67 @@
import {Color3, MeshBuilder, Observable, Scene, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core";
import {enumKeys} from "../../util/functions/enumKeys";
import {ToolType} from "../types/toolType";
import {buildTool} from "./buildTool";
import {AdvancedDynamicTexture, ColorPicker} from "@babylonjs/gui";
export function buildColor(color: Color3, scene: Scene, parent: TransformNode, index: number,
colorChangeObservable: Observable<{ oldColor: string, newColor: string }>) {
const width = 1;
const depth = .2;
const material = new StandardMaterial("material-" + color.toHexString(), scene);
material.diffuseColor = color;
const mesh = MeshBuilder.CreateBox("toolbox-color-" + color.toHexString(), {
width: width,
height: .01,
depth: depth
}, this.scene);
mesh.material = material;
mesh.position.z = index / 4;
mesh.parent = parent;
mesh.metadata = {tool: 'color'};
let i = 0;
for (const tool of enumKeys(ToolType)) {
const newItem = buildTool(ToolType[tool], mesh);
if (newItem) {
newItem.position = new Vector3(calculatePosition(++i), .1, 0);
}
}
const colorPickerPlane = MeshBuilder
.CreatePlane("colorPickerPlane",
{
width: .1,
height: .1
}, scene);
const colorPickerTexture = AdvancedDynamicTexture.CreateForMesh(colorPickerPlane, 1024, 1024);
colorPickerPlane.parent = mesh;
colorPickerPlane.position = new Vector3(calculatePosition(++i), .1, 0);
const colorPicker = new ColorPicker("color-picker");
colorPicker.scaleY = 5;
colorPicker.scaleX = 5;
colorPicker.value = color;
colorPicker.onValueChangedObservable.add((value) => {
const oldColor = material.diffuseColor.clone();
const newColor = value.clone();
material.diffuseColor = newColor;
const newColorHex = newColor.toHexString();
material.id = "material-" + newColorHex;
material.name = "material-" + newColorHex;
mesh.id = "toolbox-color-" + newColorHex;
mesh.name = "toolbox-color-" + newColorHex;
colorChangeObservable.notifyObservers({
oldColor: oldColor.toHexString(),
newColor: newColor.toHexString()
});
});
colorPickerTexture.addControl(colorPicker);
}
const GRID_SIZE = 5;
function calculatePosition(i: number) {
return (i / GRID_SIZE) - .5 - (1 / GRID_SIZE / 2);
}

View File

@ -0,0 +1,29 @@
import {ToolType} from "../types/toolType";
import {Mesh, MeshBuilder} from "@babylonjs/core";
export function buildMesh(type: ToolType, toolname: string): Mesh {
switch (type) {
case ToolType.BOX:
return MeshBuilder.CreateBox(toolname, {width: 1, height: 1, depth: 1}, this.scene);
case ToolType.SPHERE:
return MeshBuilder.CreateSphere(toolname, {diameter: 1}, this.scene);
case ToolType.CYLINDER:
return MeshBuilder.CreateCylinder(toolname, {height: 1, diameter: 1}, this.scene);
case ToolType.CONE:
return MeshBuilder.CreateCylinder(toolname, {
diameterTop: 0,
height: 1,
diameterBottom: 1
}, this.scene);
case ToolType.PLANE:
return MeshBuilder.CreatePlane(toolname, {width: 1, height: 1}, this.scene);
case ToolType.OBJECT:
return null;
}
}

View File

@ -0,0 +1,36 @@
import {AbstractMesh, Color3, InstancedMesh, StandardMaterial, Vector3} from "@babylonjs/core";
import {ToolType} from "../types/toolType";
import {buildMesh} from "./buildMesh";
const WIDGET_SIZE = .1;
export function buildTool(tool: ToolType, parent: AbstractMesh) {
const id = this.toolId(tool, (parent.material as StandardMaterial).diffuseColor);
const newItem = buildMesh(tool, `tool-${id}`);
if (!newItem) {
return null;
}
newItem.material = parent.material;
if (tool === ToolType.PLANE) {
newItem.material.backFaceCulling = false;
}
newItem.scaling = new Vector3(WIDGET_SIZE,
WIDGET_SIZE,
WIDGET_SIZE);
newItem.parent = parent;
newItem.metadata = {template: tool};
const instance = new InstancedMesh("instance-" + id, newItem);
instance.metadata = {template: tool};
instance.parent = parent;
newItem.setEnabled(false);
newItem.onEnabledStateChangedObservable.add(() => {
instance.setEnabled(false);
});
return instance;
}
function toolId(tool: ToolType, color: Color3) {
return tool + "-" + color.toHexString();
}

View File

@ -1,35 +1,15 @@
import { import {Color3, Mesh, MeshBuilder, Observable, Scene, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core";
AbstractMesh,
Color3,
InstancedMesh,
Mesh,
MeshBuilder,
Observable,
Scene,
StandardMaterial,
TransformNode,
Vector3
} from "@babylonjs/core";
import {CameraHelper} from "../util/cameraHelper"; import {Button3D, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
import {AdvancedDynamicTexture, Button3D, ColorPicker, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui"; import {ControllerEventType, Controllers} from "../controllers/controllers";
import {Controllers} from "../controllers/controllers"; import {setMenuPosition} from "../util/functions/setMenuPosition";
import {buildColor} from "./functions/buildColor";
export enum ToolType {
BOX = "#box-template",
SPHERE = "#sphere-template",
CYLINDER = "#cylinder-template",
CONE = "#cone-template",
PLANE = "#plane-template",
OBJECT = "#object-template",
}
export class Toolbox { export class Toolbox {
private index = 0; private index = 0;
private readonly scene: Scene; private readonly scene: Scene;
public readonly node: TransformNode; public readonly node: TransformNode;
private readonly manager: GUI3DManager; private readonly manager: GUI3DManager;
private readonly gridsize = 5;
private readonly addPanel: StackPanel3D; private readonly addPanel: StackPanel3D;
private readonly controllers: Controllers; private readonly controllers: Controllers;
private readonly xObserver; private readonly xObserver;
@ -51,179 +31,61 @@ export class Toolbox {
handle.id = "handle"; handle.id = "handle";
const handleMaterial = new StandardMaterial("handle-material", this.scene); const handleMaterial = new StandardMaterial("handle-material", this.scene);
handleMaterial.diffuseColor = Color3.FromHexString("#EEEEFF"); handleMaterial.diffuseColor = Color3.FromHexString("#EEEEFF");
handleMaterial.alpha = .5; handleMaterial.alpha = .8;
handle.material = handleMaterial; handle.material = handleMaterial;
handle.position = Vector3.Zero(); handle.position = Vector3.Zero();
this.node.parent = handle; this.node.parent = handle;
this.node.position.y = .1;
this.node.scaling = new Vector3(0.6, 0.6, 0.6);
this.buildToolbox(); this.buildToolbox();
if (!this.xObserver) { if (!this.xObserver) {
this.xObserver = this.controllers.controllerObserver.add((evt) => { this.xObserver = this.controllers.controllerObserver.add((evt) => {
if (evt.type == 'x-button') { if (evt.type == ControllerEventType.X_BUTTON) {
if (evt.value == 1) { if (evt.value == 1) {
this.node.parent.setEnabled(!this.node.parent.isEnabled(false)); this.node.parent.setEnabled(!this.node.parent.isEnabled(false));
CameraHelper.setMenuPosition(this.node.parent as Mesh, this.scene, setMenuPosition(this.node.parent as Mesh, this.scene,
new Vector3(0, 0, 0)); Vector3.Zero());
} }
} }
}); });
} }
} }
public buildTool(tool: ToolType, parent: AbstractMesh) {
const id = this.toolId(tool, (parent.material as StandardMaterial).diffuseColor);
const newItem = this.buildMesh(tool, `tool-${id}`);
if (!newItem) {
return null;
}
newItem.material = parent.material;
if (tool === ToolType.PLANE) {
newItem.material.backFaceCulling = false;
}
newItem.scaling = new Vector3(Toolbox.WIDGET_SIZE,
Toolbox.WIDGET_SIZE,
Toolbox.WIDGET_SIZE);
newItem.parent = parent;
newItem.metadata = {template: tool};
const instance = new InstancedMesh("instance-" + id, newItem);
instance.metadata = {template: tool};
instance.parent = parent;
newItem.setEnabled(false);
newItem.onEnabledStateChangedObservable.add(() => {
instance.setEnabled(false);
});
return instance;
}
private buildMesh(type: ToolType, toolname: string): Mesh {
switch (type) {
case ToolType.BOX:
return MeshBuilder.CreateBox(toolname, {width: 1, height: 1, depth: 1}, this.scene);
case ToolType.SPHERE:
return MeshBuilder.CreateSphere(toolname, {diameter: 1}, this.scene);
case ToolType.CYLINDER:
return MeshBuilder.CreateCylinder(toolname, {height: 1, diameter: 1}, this.scene);
case ToolType.CONE:
return MeshBuilder.CreateCylinder(toolname, {
diameterTop: 0,
height: 1,
diameterBottom: 1
}, this.scene);
case ToolType.PLANE:
return MeshBuilder.CreatePlane(toolname, {width: 1, height: 1}, this.scene);
case ToolType.OBJECT:
return null;
}
}
private toolId(tool: ToolType, color: Color3) {
return tool + "-" + color.toHexString();
}
private calculatePosition(i: number) {
return (i / this.gridsize) - .5 - (1 / this.gridsize / 2);
}
private static WIDGET_SIZE = .1;
private buildToolbox() {
this.node.position.y = .1;
this.node.scaling = new Vector3(0.6, 0.6, 0.6);
const color = "#7777FF";
this.buildColor(Color3.FromHexString(color));
const addButton = new Button3D("add-button");
const text = new TextBlock("add-button-text", "Add Color");
text.color = "white";
text.fontSize = "48px";
text.text = "Add Color";
addButton.content = text;
this.addPanel.node.parent = this.node.parent;
this.addPanel.addControl(addButton);
this.addPanel.node.scaling = new Vector3(.1, .1, .1);
this.addPanel.position = new Vector3(-.25, 0, 0);
addButton.onPointerClickObservable.add(() => {
this.buildColor(Color3.Random());
});
this.node.parent.setEnabled(false);
}
public updateToolbox(color: string) { public updateToolbox(color: string) {
if (this.scene.getMeshById("toolbox-color-" + color)) { if (this.scene.getMeshById("toolbox-color-" + color)) {
return; return;
} else { } else {
this.buildColor(Color3.FromHexString(color)); buildColor(Color3.FromHexString(color), this.scene, this.node, this.index++, this.colorChangeObservable);
} }
} }
private buildColor(color: Color3) { private buildToolbox() {
const width = 1; const color = "#7777FF";
const depth = .2; buildColor(Color3.FromHexString(color), this.scene, this.node, this.index++, this.colorChangeObservable);
const material = new StandardMaterial("material-" + color.toHexString(), this.scene); const addButton = createButton();
material.diffuseColor = color;
const mesh = MeshBuilder.CreateBox("toolbox-color-" + color.toHexString(), {
width: width,
height: .01,
depth: depth
}, this.scene);
mesh.material = material;
mesh.position.z = this.index++ / 4;
mesh.parent = this.node;
mesh.metadata = {tool: 'color'};
let i = 0;
for (const tool of enumKeys(ToolType)) {
const newItem = this.buildTool(ToolType[tool], mesh);
if (newItem) {
newItem.position = new Vector3(this.calculatePosition(++i), .1, 0);
}
}
const colorPickerPlane = MeshBuilder
.CreatePlane("colorPickerPlane",
{
width: Toolbox.WIDGET_SIZE,
height: Toolbox.WIDGET_SIZE
}, this.scene);
const colorPickerTexture = AdvancedDynamicTexture.CreateForMesh(colorPickerPlane, 1024, 1024);
colorPickerPlane.parent = mesh;
colorPickerPlane.position = new Vector3(this.calculatePosition(++i), .1, 0);
this.addPanel.node.parent = this.node.parent;
this.addPanel.addControl(addButton);
this.addPanel.node.scaling = new Vector3(.1, .1, .1);
this.addPanel.position = new Vector3(-.25, 0, 0);
const colorPicker = new ColorPicker("color-picker"); addButton.onPointerClickObservable.add(() => {
colorPicker.scaleY = 5; buildColor(Color3.Random(), this.scene, this.node, this.index++, this.colorChangeObservable);
colorPicker.scaleX = 5;
colorPicker.value = color;
colorPicker.onValueChangedObservable.add((value) => {
const oldColor = material.diffuseColor.clone();
const newColor = value.clone();
material.diffuseColor = newColor;
const newColorHex = newColor.toHexString();
material.id = "material-" + newColorHex;
material.name = "material-" + newColorHex;
mesh.id = "toolbox-color-" + newColorHex;
mesh.name = "toolbox-color-" + newColorHex;
this.colorChangeObservable.notifyObservers({
oldColor: oldColor.toHexString(),
newColor: newColor.toHexString()
});
}); });
colorPickerTexture.addControl(colorPicker); this.node.parent.setEnabled(false);
} }
} }
function enumKeys<O extends object, K extends keyof O = keyof O>(obj: O): K[] { function createButton(): Button3D {
return Object.keys(obj).filter(k => Number.isNaN(+k)) as K[]; const addButton = new Button3D("add-button");
const text = new TextBlock("add-button-text", "Add Color");
text.color = "white";
text.fontSize = "48px";
text.text = "Add Color";
addButton.content = text;
return addButton;
} }

View File

@ -0,0 +1,8 @@
export enum ToolType {
BOX = "#box-template",
SPHERE = "#sphere-template",
CYLINDER = "#cylinder-template",
CONE = "#cone-template",
PLANE = "#plane-template",
OBJECT = "#object-template",
}

View File

@ -1,11 +1,9 @@
import {Angle, Observable, Vector3} from "@babylonjs/core"; import {Observable} from "@babylonjs/core";
import log from "loglevel";
import round from "round";
import {IPersistenceManager} from "../integration/iPersistenceManager"; import {IPersistenceManager} from "../integration/iPersistenceManager";
import {AppConfigType} from "./appConfigType"; import {AppConfigType} from "./appConfigType";
export class AppConfig { export class AppConfig {
private readonly logger = log.getLogger('AppConfig');
public readonly onConfigChangedObservable = new Observable<AppConfigType>(); public readonly onConfigChangedObservable = new Observable<AppConfigType>();
private _currentConfig: AppConfigType; private _currentConfig: AppConfigType;
private persistenceManager: IPersistenceManager; private persistenceManager: IPersistenceManager;
@ -34,7 +32,6 @@ export class AppConfig {
} else { } else {
this._currentConfig = config; this._currentConfig = config;
} }
}); });
} }
return this._currentConfig; return this._currentConfig;
@ -53,34 +50,4 @@ export class AppConfig {
this._currentConfig = config; this._currentConfig = config;
this.onConfigChangedObservable.notifyObservers(this._currentConfig); this.onConfigChangedObservable.notifyObservers(this._currentConfig);
} }
public snapGridVal(value: Vector3, snap: number): Vector3 {
if (!snap) {
return value;
}
const position = value.clone();
position.x = round(value.x, snap);
position.y = round(value.y, snap);
position.z = round(value.z, snap);
return position;
}
public snapRotateVal(value: Vector3, snap: number): Vector3 {
if (!snap) {
return value;
}
const rotation = new Vector3();
rotation.x = this.snapAngle(value.x, snap);
rotation.y = this.snapAngle(value.y, snap);
rotation.z = this.snapAngle(value.z, snap);
return rotation;
}
private snapAngle(val: number, snap: number): number {
const angle = snap;
const deg = Angle.FromRadians(val).degrees();
const snappedDegrees = round(deg, angle);
this.logger.debug("deg", val, deg, snappedDegrees, angle);
return Angle.FromDegrees(snappedDegrees).radians();
}
} }

View File

@ -1,21 +0,0 @@
import {Scene, TransformNode, Vector3} from "@babylonjs/core";
export class CameraHelper {
public static getFrontPosition(distance: number, scene: Scene): Vector3 {
const offset = new Vector3(0, 0, distance);
offset.applyRotationQuaternionInPlace(scene.activeCamera.absoluteRotation);
return scene.activeCamera.globalPosition.add(offset);
}
public static setMenuPosition(node: TransformNode, scene: Scene, offset: Vector3 = Vector3.Zero()) {
const front = CameraHelper.getFrontPosition(.8, scene);
front.y = scene.activeCamera.globalPosition.y;
node.position = front;
node.position.addInPlace(offset);
node.lookAt(scene.activeCamera.globalPosition);
node.rotation.y = node.rotation.y + Math.PI;
node.position.y -= .5;
}
}

View File

@ -1,6 +1,8 @@
import {HavokPlugin, Quaternion, Scene, Vector3} from "@babylonjs/core"; import {HavokPlugin, Quaternion, Scene, Vector3} from "@babylonjs/core";
import HavokPhysics from "@babylonjs/havok"; import HavokPhysics from "@babylonjs/havok";
import {AppConfig} from "./appConfig"; import {AppConfig} from "./appConfig";
import {snapGridVal} from "./functions/snapGridVal";
import {snapRotateVal} from "./functions/snapRotateVal";
export class CustomPhysics { export class CustomPhysics {
private readonly scene: Scene; private readonly scene: Scene;
@ -27,12 +29,12 @@ export class CustomPhysics {
body.disablePreStep = false; body.disablePreStep = false;
const pos: Vector3 = body.getObjectCenterWorld(); const pos: Vector3 = body.getObjectCenterWorld();
const val: Vector3 = this.config.snapGridVal(pos, const val: Vector3 = snapGridVal(pos,
this.config.current.gridSnap); this.config.current.gridSnap);
body.transformNode.position.set(val.x, val.y, val.z); body.transformNode.position.set(val.x, val.y, val.z);
const rot: Quaternion = const rot: Quaternion =
Quaternion.FromEulerVector( Quaternion.FromEulerVector(
this.config.snapRotateVal(body.transformNode.rotationQuaternion.toEulerAngles(), snapRotateVal(body.transformNode.rotationQuaternion.toEulerAngles(),
this.config.current.rotateSnap)) this.config.current.rotateSnap))
body.transformNode.rotationQuaternion.set( body.transformNode.rotationQuaternion.set(

View File

@ -0,0 +1,3 @@
export function enumKeys<O extends object, K extends keyof O = keyof O>(obj: O): K[] {
return Object.keys(obj).filter(k => Number.isNaN(+k)) as K[];
}

View File

@ -0,0 +1,7 @@
import {Scene, Vector3} from "@babylonjs/core";
export function getFrontPosition(distance: number, scene: Scene): Vector3 {
const offset = new Vector3(0, 0, distance);
offset.applyRotationQuaternionInPlace(scene.activeCamera.absoluteRotation);
return scene.activeCamera.globalPosition.add(offset);
}

View File

@ -0,0 +1,13 @@
import {Scene, TransformNode, Vector3} from "@babylonjs/core";
import {getFrontPosition} from "./getFrontPosition";
export function setMenuPosition(node: TransformNode, scene: Scene, offset: Vector3 = Vector3.Zero()) {
const front = getFrontPosition(.8, scene);
front.y = scene.activeCamera.globalPosition.y;
node.position = front;
node.position.addInPlace(offset);
node.lookAt(scene.activeCamera.globalPosition);
node.rotation.y = node.rotation.y + Math.PI;
node.position.y -= .5;
}

View File

@ -0,0 +1,13 @@
import {Vector3} from "@babylonjs/core";
import round from "round";
export function snapGridVal(value: Vector3, snap: number): Vector3 {
if (!snap) {
return value;
}
const position =
new Vector3(round(value.x, snap),
round(value.y, snap),
round(value.z, snap))
return position;
}

View File

@ -0,0 +1,24 @@
import {Angle, Vector3} from "@babylonjs/core";
import round from "round";
import log from "loglevel";
const logger = log.getLogger('snapRotateVal');
export function snapRotateVal(value: Vector3, snap: number): Vector3 {
if (!snap) {
return value;
}
const rotation = new Vector3(
snapAngle(value.x, snap),
snapAngle(value.y, snap),
snapAngle(value.z, snap));
return rotation;
}
function snapAngle(val: number, snap: number): number {
const angle = snap;
const deg = Angle.FromRadians(val).degrees();
const snappedDegrees = round(deg, angle);
logger.debug("deg", val, deg, snappedDegrees, angle);
return Angle.FromDegrees(snappedDegrees).radians();
}