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="questLaunch"><a href="https://www.oculus.com/open_url/?url=https://www.deepdiagram.com/">Launch On Quest</a>
</div>
<input id="textInput" type="text"/>
<script type="module" src="./src/app.ts"></script>
</body>
</html>

279
package-lock.json generated
View File

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

View File

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

View File

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

View File

@ -1,11 +1,34 @@
import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
export type ControllerEventType = {
type: string,
export type ControllerEvent = {
type: ControllerEventType,
value?: number,
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 {
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 {Base} from "./base";
import {Controllers} from "./controllers";
import {ControllerEventType, Controllers} from "./controllers";
import log from "loglevel";
import {ConfigMenu} from "../menus/configMenu";
import {DiagramManager} from "../diagram/diagramManager";
@ -13,7 +13,7 @@ export class Left extends Base {
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
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) => {
if (init.components['xr-standard-thumbstick']) {
init.components['xr-standard-thumbstick']
@ -31,7 +31,7 @@ export class Left extends Base {
if (value.pressed) {
log.trace('Left', 'thumbstick changed');
this.controllers.controllerObserver.notifyObservers({
type: 'decreaseVelocity',
type: ControllerEventType.DECREASE_VELOCITY,
value: value.value
});
}
@ -44,7 +44,10 @@ export class Left extends Base {
if (xbutton) {
xbutton.onButtonStateChangedObservable.add((button) => {
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) {
ybutton.onButtonStateChangedObservable.add((button) => {
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 }) {
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;
} else {
Base.stickVector.x = 0;
}
if (Math.abs(value.y) > .1) {
this.controllers.controllerObserver.notifyObservers({
type: 'forwardback',
type: ControllerEventType.FORWARD_BACK,
value: value.y * this.speedFactor
});
Base.stickVector.y = 1;
@ -91,8 +100,8 @@ export class Left extends Base {
}
if (Base.stickVector.equals(Vector3.Zero())) {
this.controllers.controllerObserver.notifyObservers({type: 'leftright', value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'forwardback', value: 0});
this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.LEFT_RIGHT, value: 0});
this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.FORWARD_BACK, value: 0});
} else {
}

View File

@ -1,6 +1,6 @@
import {Base} from "./base";
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Controllers} from "./controllers";
import {ControllerEventType, Controllers} from "./controllers";
import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager";
@ -21,7 +21,10 @@ export class Right extends Base {
if (bbutton) {
bbutton.onButtonStateChangedObservable.add((button) => {
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
.add((button) => {
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) => {
if (value.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) => {
if (value.pressed) {
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) {
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 {
this.controllers.controllerObserver.notifyObservers({type: 'turn', value: 0});
this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.TURN, value: 0});
}
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;
} else {
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
this.controllers.controllerObserver.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0});
Base.stickVector.z = 0;
}
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 {Left} from "./left";
import {EditMenu} from "../menus/editMenu";
import {Controllers} from "./controllers";
import {ControllerEvent, ControllerEventType, Controllers} from "./controllers";
import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager";
@ -90,7 +90,7 @@ export class Rigplatform {
this.controllers = controllers;
Rigplatform.xr = xr;
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.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene);
@ -125,38 +125,35 @@ export class Rigplatform {
private registerObserver() {
if (!this.registered) {
this.registered = true;
this.controllers.controllerObserver.add((event: { type: string, value: number }) => {
this.controllers.controllerObserver.add((event: ControllerEvent) => {
switch (event.type) {
case "increaseVelocity":
case ControllerEventType.INCREASE_VELOCITY:
if (this.velocityIndex < this.velocityArray.length - 1) {
this.velocityIndex++;
} else {
this.velocityIndex = 0;
}
break;
case "decreaseVelocity":
case ControllerEventType.DECREASE_VELOCITY:
if (this.velocityIndex > 0) {
this.velocityIndex--;
} else {
this.velocityIndex = this.velocityArray.length - 1;
}
break;
case "turn":
case ControllerEventType.TURN:
this.turn(event.value);
break;
case "forwardback":
case ControllerEventType.FORWARD_BACK:
this.forwardback(event.value);
break;
case "leftright":
case ControllerEventType.LEFT_RIGHT:
this.leftright(event.value);
break;
case "updown":
case ControllerEventType.UP_DOWN:
this.updown(event.value);
break;
case "stop":
log.warn("Rigplatform", "stop is no longer implemented");
break;
case "menu":
case ControllerEventType.MENU:
this.bMenu.toggle();
break;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,11 @@
import {AdvancedDynamicTexture, RadioGroup, SelectionPanel} from "@babylonjs/gui";
import {AbstractMesh, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
import {CameraHelper} from "../util/cameraHelper";
import {AbstractMesh, MeshBuilder, Scene, WebXRDefaultExperience} from "@babylonjs/core";
import log from "loglevel";
import {AppConfig} from "../util/appConfig";
import {Controllers} from "../controllers/controllers";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {DiaSounds} from "../util/diaSounds";
import {AbstractMenu} from "./abstractMenu";
import {setMenuPosition} from "../util/functions/setMenuPosition";
export class ConfigMenu extends AbstractMenu {
private sounds: DiaSounds;
@ -21,6 +21,28 @@ export class ConfigMenu extends AbstractMenu {
{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() {
if (this.configPlane) {
this.sounds.exit.play();
@ -48,28 +70,7 @@ export class ConfigMenu extends AbstractMenu {
this.buildRotationSnapControl(selectionPanel);
this.buildTurnSnapControl(selectionPanel);
CameraHelper.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();
}
});
}
setMenuPosition(this.configPlane, this.scene);
}
private buildCreateScaleControl(selectionPanel: SelectionPanel): RadioGroup {

View File

@ -9,7 +9,7 @@ import {
Scene,
StandardMaterial,
Vector3,
WebXRDefaultExperience
WebXRDefaultExperience,
} from "@babylonjs/core";
import {Button3D, GUI3DManager, PlanePanel, TextBlock} from "@babylonjs/gui";
import {DiagramManager} from "../diagram/diagramManager";
@ -18,20 +18,20 @@ import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
import log from "loglevel";
import {InputTextView} from "../information/inputTextView";
import {DiaSounds} from "../util/diaSounds";
import {CameraHelper} from "../util/cameraHelper";
import {TextLabel} from "../diagram/textLabel";
import {DiagramConnection} from "../diagram/diagramConnection";
import {GLTF2Export} from "@babylonjs/serializers";
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 manager: GUI3DManager;
private readonly scene: Scene;
private paintColor: string = null;
private readonly logger: log.Logger = log.getLogger('EditMenu');
private gizmoManager: GizmoManager;
private readonly xr: WebXRDefaultExperience;
private readonly diagramManager: DiagramManager;
private connection: DiagramConnection = null;
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.xr = xr;
this.sounds = new DiaSounds(scene);
this.diagramManager = diagramManager;
this.gizmoManager = new GizmoManager(scene);
@ -129,7 +129,7 @@ export class EditMenu {
} else {
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;
}
}
@ -251,13 +251,15 @@ export class EditMenu {
if (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.onTextObservable.addOnce((value) => {
this.persist(mesh, value.text);
TextLabel.updateTextNode(mesh, value.text);
});
}
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 {AbstractMenu} from "./abstractMenu";
import {AdvancedDynamicTexture, Grid, TextBlock} from "@babylonjs/gui";
import {CameraHelper} from "../util/cameraHelper";
import {setMenuPosition} from "../util/functions/setMenuPosition";
export class IntegrationMenu extends AbstractMenu {
private plane: AbstractMesh = null;
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
super(scene, xr, controllers);
this.buildMenu();
}
@ -28,7 +28,7 @@ export class IntegrationMenu extends AbstractMenu {
grid.addControl(labelText1, 0, 0);
const labelText2 = new TextBlock("labelText1", "New Relic Account");
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 {
AbstractMesh,
Color3,
InstancedMesh,
Mesh,
MeshBuilder,
Observable,
Scene,
StandardMaterial,
TransformNode,
Vector3
} from "@babylonjs/core";
import {Color3, Mesh, MeshBuilder, Observable, Scene, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core";
import {CameraHelper} from "../util/cameraHelper";
import {AdvancedDynamicTexture, Button3D, ColorPicker, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
import {Controllers} from "../controllers/controllers";
export enum ToolType {
BOX = "#box-template",
SPHERE = "#sphere-template",
CYLINDER = "#cylinder-template",
CONE = "#cone-template",
PLANE = "#plane-template",
OBJECT = "#object-template",
}
import {Button3D, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {setMenuPosition} from "../util/functions/setMenuPosition";
import {buildColor} from "./functions/buildColor";
export class Toolbox {
private index = 0;
private readonly scene: Scene;
public readonly node: TransformNode;
private readonly manager: GUI3DManager;
private readonly gridsize = 5;
private readonly addPanel: StackPanel3D;
private readonly controllers: Controllers;
private readonly xObserver;
@ -51,179 +31,61 @@ export class Toolbox {
handle.id = "handle";
const handleMaterial = new StandardMaterial("handle-material", this.scene);
handleMaterial.diffuseColor = Color3.FromHexString("#EEEEFF");
handleMaterial.alpha = .5;
handleMaterial.alpha = .8;
handle.material = handleMaterial;
handle.position = Vector3.Zero();
this.node.parent = handle;
this.node.position.y = .1;
this.node.scaling = new Vector3(0.6, 0.6, 0.6);
this.buildToolbox();
if (!this.xObserver) {
this.xObserver = this.controllers.controllerObserver.add((evt) => {
if (evt.type == 'x-button') {
if (evt.type == ControllerEventType.X_BUTTON) {
if (evt.value == 1) {
this.node.parent.setEnabled(!this.node.parent.isEnabled(false));
CameraHelper.setMenuPosition(this.node.parent as Mesh, this.scene,
new Vector3(0, 0, 0));
setMenuPosition(this.node.parent as Mesh, this.scene,
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) {
if (this.scene.getMeshById("toolbox-color-" + color)) {
return;
} 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 depth = .2;
const material = new StandardMaterial("material-" + color.toHexString(), this.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 = 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);
const color = "#7777FF";
buildColor(Color3.FromHexString(color), this.scene, this.node, this.index++, this.colorChangeObservable);
const addButton = createButton();
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");
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;
this.colorChangeObservable.notifyObservers({
oldColor: oldColor.toHexString(),
newColor: newColor.toHexString()
});
addButton.onPointerClickObservable.add(() => {
buildColor(Color3.Random(), this.scene, this.node, this.index++, this.colorChangeObservable);
});
colorPickerTexture.addControl(colorPicker);
this.node.parent.setEnabled(false);
}
}
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[];
function createButton(): Button3D {
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 log from "loglevel";
import round from "round";
import {Observable} from "@babylonjs/core";
import {IPersistenceManager} from "../integration/iPersistenceManager";
import {AppConfigType} from "./appConfigType";
export class AppConfig {
private readonly logger = log.getLogger('AppConfig');
public readonly onConfigChangedObservable = new Observable<AppConfigType>();
private _currentConfig: AppConfigType;
private persistenceManager: IPersistenceManager;
@ -34,7 +32,6 @@ export class AppConfig {
} else {
this._currentConfig = config;
}
});
}
return this._currentConfig;
@ -53,34 +50,4 @@ export class AppConfig {
this._currentConfig = config;
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 HavokPhysics from "@babylonjs/havok";
import {AppConfig} from "./appConfig";
import {snapGridVal} from "./functions/snapGridVal";
import {snapRotateVal} from "./functions/snapRotateVal";
export class CustomPhysics {
private readonly scene: Scene;
@ -27,12 +29,12 @@ export class CustomPhysics {
body.disablePreStep = false;
const pos: Vector3 = body.getObjectCenterWorld();
const val: Vector3 = this.config.snapGridVal(pos,
const val: Vector3 = snapGridVal(pos,
this.config.current.gridSnap);
body.transformNode.position.set(val.x, val.y, val.z);
const rot: Quaternion =
Quaternion.FromEulerVector(
this.config.snapRotateVal(body.transformNode.rotationQuaternion.toEulerAngles(),
snapRotateVal(body.transformNode.rotationQuaternion.toEulerAngles(),
this.config.current.rotateSnap))
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();
}