mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
Cowboy prototyping
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
@fortawesome:registry=https://npm.fontawesome.com/
|
||||
//npm.fontawesome.com/:_authToken=104779DB-FD41-4BEA-BDB4-B1845D758A79
|
||||
Generated
+1
@@ -2856,6 +2856,7 @@ name = "studio"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bitflags 2.4.0",
|
||||
"console_error_panic_hook",
|
||||
"parking_lot",
|
||||
"wasm-bindgen",
|
||||
|
||||
Generated
+577
@@ -9,6 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-pro": "^6.4.2",
|
||||
"lit": "^2.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"tslib": "^2.3.0"
|
||||
@@ -2387,6 +2388,14 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-pro": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-pro/-/6.4.2/fontawesome-pro-6.4.2.tgz",
|
||||
"integrity": "sha512-b7VtzrgoASuCbnWJ1A17Sw3wemaFGukyBk0Y2ks/rgcnhlJ1uzdyv2uM3QbEaq9OgyZAKGJD1Tli6qHRI68zSQ==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
@@ -2536,6 +2545,17 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/source-map": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
|
||||
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
@@ -3671,6 +3691,28 @@
|
||||
"@types/chai": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "8.44.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.4.tgz",
|
||||
"integrity": "sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint-scope": {
|
||||
"version": "3.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz",
|
||||
"integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/eslint": "*",
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz",
|
||||
@@ -3683,6 +3725,13 @@
|
||||
"integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz",
|
||||
"integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.14.199",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz",
|
||||
@@ -3831,6 +3880,181 @@
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
|
||||
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/helper-numbers": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
|
||||
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-api-error": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
|
||||
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-buffer": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
|
||||
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-numbers": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
|
||||
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
|
||||
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
|
||||
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/wasm-gen": "1.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ieee754": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
|
||||
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@xtuc/ieee754": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/leb128": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
|
||||
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/utf8": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
|
||||
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-edit": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
|
||||
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-section": "1.11.6",
|
||||
"@webassemblyjs/wasm-gen": "1.11.6",
|
||||
"@webassemblyjs/wasm-opt": "1.11.6",
|
||||
"@webassemblyjs/wasm-parser": "1.11.6",
|
||||
"@webassemblyjs/wast-printer": "1.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-gen": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
|
||||
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/ieee754": "1.11.6",
|
||||
"@webassemblyjs/leb128": "1.11.6",
|
||||
"@webassemblyjs/utf8": "1.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-opt": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
|
||||
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||
"@webassemblyjs/wasm-gen": "1.11.6",
|
||||
"@webassemblyjs/wasm-parser": "1.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-parser": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
|
||||
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/ieee754": "1.11.6",
|
||||
"@webassemblyjs/leb128": "1.11.6",
|
||||
"@webassemblyjs/utf8": "1.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wast-printer": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
|
||||
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@xtuc/long": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@yarnpkg/lockfile": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
|
||||
@@ -3902,6 +4126,16 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-import-assertions": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
|
||||
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"acorn": "^8"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
|
||||
@@ -3948,6 +4182,16 @@
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-colors": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||
@@ -4504,6 +4748,16 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/chrome-trace-event": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||
@@ -4606,6 +4860,13 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -4889,6 +5150,20 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.15.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
|
||||
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/enquirer": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
|
||||
@@ -4922,6 +5197,13 @@
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz",
|
||||
"integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
|
||||
@@ -4977,6 +5259,30 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope/node_modules/estraverse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
@@ -5002,6 +5308,19 @@
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/esrecurse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estraverse": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
@@ -5032,6 +5351,16 @@
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/events": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@@ -5377,6 +5706,13 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-to-regexp": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
@@ -5950,6 +6286,37 @@
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
|
||||
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"merge-stream": "^2.0.0",
|
||||
"supports-color": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/jju": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
|
||||
@@ -6113,6 +6480,16 @@
|
||||
"@types/trusted-types": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/loader-runner": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
||||
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.11.5"
|
||||
}
|
||||
},
|
||||
"node_modules/loader-utils": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
@@ -6260,6 +6637,13 @@
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
@@ -6442,6 +6826,13 @@
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz",
|
||||
@@ -7109,6 +7500,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
@@ -7432,6 +7833,25 @@
|
||||
"node": ">=v12.22.7"
|
||||
}
|
||||
},
|
||||
"node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/secure-compare": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
|
||||
@@ -7471,6 +7891,16 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
|
||||
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
@@ -7743,6 +8173,16 @@
|
||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
|
||||
@@ -7794,6 +8234,71 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.21.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.21.0.tgz",
|
||||
"integrity": "sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
"commander": "^2.20.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"bin": {
|
||||
"terser": "bin/terser"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin": {
|
||||
"version": "5.3.9",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
|
||||
"integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jest-worker": "^27.4.5",
|
||||
"schema-utils": "^3.1.1",
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"terser": "^5.16.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^5.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
},
|
||||
"esbuild": {
|
||||
"optional": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/terser/node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/test-exclude": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
|
||||
@@ -8492,6 +8997,20 @@
|
||||
"wasm-pack": "run.js"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
@@ -8510,6 +9029,64 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.88.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
|
||||
"integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^1.0.0",
|
||||
"@webassemblyjs/ast": "^1.11.5",
|
||||
"@webassemblyjs/wasm-edit": "^1.11.5",
|
||||
"@webassemblyjs/wasm-parser": "^1.11.5",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"browserslist": "^4.14.5",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.15.0",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.2.9",
|
||||
"json-parse-even-better-errors": "^2.3.1",
|
||||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^3.2.0",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.3.7",
|
||||
"watchpack": "^2.4.0",
|
||||
"webpack-sources": "^3.2.3"
|
||||
},
|
||||
"bin": {
|
||||
"webpack": "bin/webpack.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"webpack-cli": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-sources": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"wasm-pack": "^0.12.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-pro": "^6.4.2",
|
||||
"lit": "^2.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"tslib": "^2.3.0"
|
||||
|
||||
@@ -10,6 +10,91 @@
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.toolbar-group {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.btn-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
font-size: 15px;
|
||||
padding: 10px 12px;
|
||||
pointer-events: auto;
|
||||
|
||||
// TODO: Copypasta
|
||||
background: #0006;
|
||||
color: #FFFC;
|
||||
backdrop-filter: blur(16px);
|
||||
transition: {
|
||||
property: background, color;
|
||||
duration: 0.1s;
|
||||
timing-function: linear;
|
||||
}
|
||||
mix-blend-mode: multiply;
|
||||
|
||||
&:first-child {
|
||||
border: {
|
||||
top-left-radius: 8px;
|
||||
bottom-left-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border: {
|
||||
top-right-radius: 8px;
|
||||
bottom-right-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #0008;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
&:has(:checked) {
|
||||
background: #7A2C34E3;
|
||||
color: #FFF;
|
||||
background-blend-mode: multiply;
|
||||
|
||||
&:hover {
|
||||
background: #90363F;
|
||||
}
|
||||
}
|
||||
|
||||
&:has(:disabled) {
|
||||
background: #0003 !important;
|
||||
color: #FFF6 !important;
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
appearance: none;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.help {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import { on } from "@storyteller/framework";
|
||||
import * as studio from "@storyteller/studio";
|
||||
import { ViewportSize } from "@storyteller/studio";
|
||||
import { TransformSpace, ViewportSize } from "@storyteller/studio";
|
||||
import { LitElement, html, unsafeCSS } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
|
||||
import "./button.element";
|
||||
import "./help.element";
|
||||
import "./icons/fa-circle-info.element";
|
||||
import "./icon.element";
|
||||
|
||||
import styles from "./app.element.scss?inline";
|
||||
import { match } from "@storyteller/utility";
|
||||
|
||||
// FIXME: Figure out how to generate the correct code from `wasm_bindgen`
|
||||
enum InteractionTransform {
|
||||
TRANSLATE = 0b0001,
|
||||
ROTATE = 0b0010,
|
||||
}
|
||||
|
||||
@customElement("app-root")
|
||||
export class AppElement extends LitElement {
|
||||
@@ -16,6 +23,12 @@ export class AppElement extends LitElement {
|
||||
|
||||
@state() showHelp = false;
|
||||
|
||||
@state() transformSpace: "local"|"world" = "local";
|
||||
|
||||
@state() translateGizmoEnabled = true;
|
||||
@state() rotateGizmoEnabled = true;
|
||||
@state() scaleGizmoEnabled = false;
|
||||
|
||||
#studioCanvas?: HTMLCanvasElement | null;
|
||||
|
||||
override connectedCallback(): void {
|
||||
@@ -34,6 +47,58 @@ export class AppElement extends LitElement {
|
||||
this.showHelp = !this.showHelp;
|
||||
}
|
||||
|
||||
onSpaceChange(event: InputEvent): void {
|
||||
const { value } = event.target as HTMLInputElement;
|
||||
if (value === this.transformSpace)
|
||||
return;
|
||||
|
||||
match (value, {
|
||||
"local": () => studio.setTransformSpace(TransformSpace.Local),
|
||||
"world": () => studio.setTransformSpace(TransformSpace.World),
|
||||
_: () => {
|
||||
console.warn(`Unknown transform space: "${value}"`);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
this.transformSpace = value as "local"|"world";
|
||||
}
|
||||
|
||||
onGizmoToggled(event: InputEvent): void {
|
||||
const { name, checked } = event.target as HTMLInputElement;
|
||||
match (name, {
|
||||
"translate": () => {
|
||||
if (this.translateGizmoEnabled === checked)
|
||||
return;
|
||||
|
||||
this.translateGizmoEnabled = checked;
|
||||
},
|
||||
"rotate": () => {
|
||||
if (this.rotateGizmoEnabled === checked)
|
||||
return;
|
||||
|
||||
this.rotateGizmoEnabled = checked;
|
||||
},
|
||||
"scale": () => {
|
||||
if (this.scaleGizmoEnabled === checked)
|
||||
return;
|
||||
|
||||
this.scaleGizmoEnabled = checked;
|
||||
},
|
||||
_: () => {
|
||||
console.warn(`Unknown gizmo name: "${name}"`);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
let transform = 0;
|
||||
if (this.translateGizmoEnabled) transform |= InteractionTransform.TRANSLATE;
|
||||
if (this.rotateGizmoEnabled) transform |= InteractionTransform.ROTATE;
|
||||
// TODO: Scale
|
||||
|
||||
studio.setInteractionTransform(transform);
|
||||
}
|
||||
|
||||
#initStudio(): HTMLCanvasElement | null {
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
@@ -48,6 +113,54 @@ export class AppElement extends LitElement {
|
||||
}
|
||||
|
||||
protected override render = () => html`
|
||||
<!-- TODO: What's a "component"? -->
|
||||
<div class="toolbar" role="toolbar">
|
||||
<div class="toolbar-group" role="group">
|
||||
<label class="btn-toggle">
|
||||
<sts-icon icon=${"cube"}>Local</sts-icon>
|
||||
<input type="radio"
|
||||
name="transform-space"
|
||||
value="local"
|
||||
checked
|
||||
@input=${this.onSpaceChange}
|
||||
/>
|
||||
</label>
|
||||
<label class="btn-toggle">
|
||||
<sts-icon icon="globe">Global</sts-icon>
|
||||
<input type="radio"
|
||||
name="transform-space"
|
||||
value="world"
|
||||
@input=${this.onSpaceChange}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="toolbar-group" role="group">
|
||||
<label class="btn-toggle">
|
||||
<sts-icon icon="up-down-left-right">Translate</sts-icon>
|
||||
<input type="checkbox"
|
||||
name="translate"
|
||||
checked
|
||||
@input=${this.onGizmoToggled}
|
||||
/>
|
||||
</label>
|
||||
<label class="btn-toggle">
|
||||
<sts-icon icon="rotate">Rotate</sts-icon>
|
||||
<input type="checkbox"
|
||||
name="rotate"
|
||||
checked
|
||||
@input=${this.onGizmoToggled}
|
||||
/>
|
||||
</label>
|
||||
<label class="btn-toggle">
|
||||
<sts-icon icon="scale">Scale</sts-icon>
|
||||
<input type="checkbox"
|
||||
name="scale"
|
||||
disabled
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<sts-button class="btn-help"
|
||||
icon="circle-info"
|
||||
@click=${this.toggleHelp}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { match } from "@storyteller/utility";
|
||||
import { on } from "@storyteller/framework";
|
||||
import { LitElement, html, unsafeCSS } from "lit";
|
||||
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import styles from "./button.element.scss?inline";
|
||||
@@ -21,10 +20,10 @@ export class ButtonElement extends LitElement {
|
||||
}
|
||||
|
||||
protected override render = () => html`
|
||||
${match (this.icon, {
|
||||
"circle-info": () => html`<fa-circle-info class="icon"></fa-circle-info>`,
|
||||
_: () => null,
|
||||
})}
|
||||
${this.icon
|
||||
? html`<sts-icon icon=${this.icon} aria-hidden="true"></sts-icon>`
|
||||
: nothing}
|
||||
|
||||
<slot></slot>
|
||||
`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
:host {
|
||||
display: flex;
|
||||
width: auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
.a11y-label {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
border: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.svg-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
svg {
|
||||
height: 1em;
|
||||
fill: currentColor;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { match } from "@storyteller/utility";
|
||||
import { ElementPart, LitElement, html, nothing, unsafeCSS } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { Directive, directive } from "lit/directive.js";
|
||||
import { unsafeSVG } from "lit/directives/unsafe-svg.js";
|
||||
|
||||
import fasCircleInfo from "@fortawesome/fontawesome-pro/svgs/solid/circle-info.svg?raw";
|
||||
import fasCube from "@fortawesome/fontawesome-pro/svgs/solid/cube.svg?raw";
|
||||
import fasGlobe from "@fortawesome/fontawesome-pro/svgs/solid/globe.svg?raw";
|
||||
import fasUpDownLeftRight from "@fortawesome/fontawesome-pro/svgs/solid/up-down-left-right.svg?raw";
|
||||
import fasRotate from "@fortawesome/fontawesome-pro/svgs/solid/rotate.svg?raw";
|
||||
import fasScale from "@fortawesome/fontawesome-pro/svgs/solid/arrow-up-right-and-arrow-down-left-from-center.svg?raw";
|
||||
|
||||
import styles from "./icon.element.scss?inline";
|
||||
|
||||
@customElement("sts-icon")
|
||||
export class IconElement extends LitElement {
|
||||
static override styles = unsafeCSS(styles);
|
||||
|
||||
@property() icon = "";
|
||||
|
||||
protected override render = () => html`
|
||||
<span class="a11y-label">
|
||||
<slot></slot>
|
||||
</span>
|
||||
<div class="svg-wrapper" role="presentation">
|
||||
${match (this.icon, {
|
||||
"circle-info": () => renderSvg(fasCircleInfo),
|
||||
"cube": () => renderSvg(fasCube),
|
||||
"globe": () => renderSvg(fasGlobe),
|
||||
"up-down-left-right": () => renderSvg(fasUpDownLeftRight),
|
||||
"rotate": () => renderSvg(fasRotate),
|
||||
"scale": () => renderSvg(fasScale),
|
||||
_: () => nothing,
|
||||
})}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// TODO: Consider moving this
|
||||
function renderSvg(fullSvg: string) {
|
||||
console.log("parsing:", fullSvg);
|
||||
|
||||
const [, attrsString, body] = fullSvg.match(/<svg(.+?)>(.+?)<\/svg>/)!;
|
||||
const attrs = Object.fromEntries(
|
||||
Array.from(attrsString.matchAll(/([-:_a-zA-Z0-9]+)(?:=['"]?([^'"]*)['"]?)/g))
|
||||
.map(([, attr, value]) => [attr, value])
|
||||
);
|
||||
|
||||
return html`
|
||||
<svg ${spread(attrs)}>
|
||||
${unsafeSVG(body)}
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
|
||||
// TODO: Definitely move this
|
||||
const spread = directive(class extends Directive {
|
||||
override render(_: Record<string, string>) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
override update(part: ElementPart, [attrs]: [Record<string, string>]) {
|
||||
for (let [key, value] of Object.entries(attrs)) {
|
||||
part.element.setAttribute(key, value);
|
||||
}
|
||||
return part;
|
||||
}
|
||||
});
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
declare module "*.svg?raw" {
|
||||
const svg: string;
|
||||
export default svg;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ path = "src/main.rs"
|
||||
wasm-bindgen = { version = "0.2.84" }
|
||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
parking_lot = "0.12.1"
|
||||
bitflags = "2.4.0"
|
||||
|
||||
[features]
|
||||
wasm = ["dep:console_error_panic_hook"]
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
use bevy::{prelude::*, window::PrimaryWindow};
|
||||
|
||||
use super::{InteractionMode, InteractionTransform, Selected, TransformSpace};
|
||||
|
||||
pub(super) fn draw(
|
||||
q_selection: Query<&GlobalTransform, With<Selected>>,
|
||||
q_camera_xform: Query<&Transform, With<Camera>>,
|
||||
q_window: Query<&Window, With<PrimaryWindow>>,
|
||||
interaction_mode: Res<InteractionMode>,
|
||||
mut gizmos: Gizmos,
|
||||
mut config: ResMut<GizmoConfig>,
|
||||
) {
|
||||
if !q_selection.is_empty() {
|
||||
// TODO: Use an app state or something so we only have to set this up once
|
||||
let scale_factor = q_window.single().scale_factor() as f32;
|
||||
config.line_width = 4. * scale_factor;
|
||||
config.line_perspective = false;
|
||||
config.depth_bias = -1.;
|
||||
|
||||
let InteractionMode { transform, space } = *interaction_mode;
|
||||
let camera_xform = q_camera_xform.single();
|
||||
|
||||
// TODO: We only want to render one gizmo -- this is just for testing
|
||||
for world_xform in q_selection.iter() {
|
||||
let xform = world_xform.compute_transform();
|
||||
// Note: Scaling the gizmo size by this isn't perfect due to
|
||||
// distortion from the perspective projection. It bugged me at
|
||||
// first, but even Blender exhibits this type of gizmo distortion if
|
||||
// you dial the camera's focal length way down, so I'm gonna call it
|
||||
// good enough.
|
||||
let dist = Vec3::distance(camera_xform.translation, xform.translation);
|
||||
|
||||
if transform.contains(InteractionTransform::TRANSLATE) {
|
||||
draw_translate_gizmo(&xform, &mut gizmos, space, dist / 14.);
|
||||
}
|
||||
if transform.contains(InteractionTransform::ROTATE) {
|
||||
draw_rotate_gizmo(&xform, &mut gizmos, space, dist / 20.);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn draw_translate_gizmo(xform: &Transform, gizmos: &mut Gizmos, space: TransformSpace, size: f32) {
|
||||
let origin = xform.translation;
|
||||
let basis = match space {
|
||||
TransformSpace::Local => xform,
|
||||
TransformSpace::World => &Transform::IDENTITY,
|
||||
};
|
||||
|
||||
let mut draw_axis = |direction: Vec3, color: Color| {
|
||||
let end = origin + direction * size;
|
||||
gizmos.line(origin, end, color);
|
||||
};
|
||||
|
||||
draw_axis(basis.local_x(), Color::RED);
|
||||
draw_axis(basis.local_y(), Color::GREEN);
|
||||
draw_axis(basis.local_z(), Color::BLUE);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn draw_rotate_gizmo(xform: &Transform, gizmos: &mut Gizmos, space: TransformSpace, radius: f32) {
|
||||
let origin = xform.translation;
|
||||
let basis = match space {
|
||||
TransformSpace::Local => xform,
|
||||
TransformSpace::World => &Transform::IDENTITY,
|
||||
};
|
||||
|
||||
gizmos.circle(origin, basis.local_x(), radius, Color::RED);
|
||||
gizmos.circle(origin, basis.local_y(), radius, Color::GREEN);
|
||||
gizmos.circle(origin, basis.local_z(), radius, Color::BLUE);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
use bevy::prelude::*;
|
||||
use bitflags::bitflags;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod gizmos;
|
||||
|
||||
pub struct InteractionPlugin;
|
||||
|
||||
impl Plugin for InteractionPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(SelectionMode::default())
|
||||
.insert_resource(InteractionMode::default())
|
||||
.add_systems(Update, gizmos::draw);
|
||||
|
||||
app.add_systems(
|
||||
PreUpdate,
|
||||
(wasm::update_selection_mode, wasm::update_interaction_mode),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Copy)]
|
||||
pub struct Selectable(SelectionChannel);
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[wasm_bindgen]
|
||||
pub enum SelectionChannel {
|
||||
Objects,
|
||||
Bones,
|
||||
Widgets,
|
||||
}
|
||||
|
||||
impl Default for SelectionChannel {
|
||||
fn default() -> Self {
|
||||
Self::Objects
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Copy)]
|
||||
pub struct Selected;
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct SelectionMode(SelectionChannel);
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct InteractionMode {
|
||||
pub transform: InteractionTransform,
|
||||
pub space: TransformSpace,
|
||||
}
|
||||
|
||||
impl Default for InteractionMode {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
transform: InteractionTransform::TRANSLATE | InteractionTransform::ROTATE,
|
||||
space: default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[wasm_bindgen]
|
||||
pub struct InteractionTransform(u8);
|
||||
|
||||
bitflags! {
|
||||
impl InteractionTransform: u8 {
|
||||
const TRANSLATE = 0b0001;
|
||||
const ROTATE = 0b0010;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[wasm_bindgen]
|
||||
pub enum TransformSpace {
|
||||
Local,
|
||||
World,
|
||||
}
|
||||
|
||||
impl Default for TransformSpace {
|
||||
fn default() -> Self {
|
||||
Self::Local
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(target_arch = "wasm32")]
|
||||
pub mod wasm {
|
||||
use bevy::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::wasm::{self, WasmMessageBuffer};
|
||||
|
||||
use super::{
|
||||
InteractionMode, InteractionTransform, SelectionChannel, SelectionMode, TransformSpace,
|
||||
};
|
||||
|
||||
static SELECT_MODE_BUF: WasmMessageBuffer<SelectionChannel> = WasmMessageBuffer::new();
|
||||
static INTERACTION_TRANSFORM_BUF: WasmMessageBuffer<InteractionTransform> =
|
||||
WasmMessageBuffer::new();
|
||||
static INTERACTION_SPACE_BUF: WasmMessageBuffer<TransformSpace> = WasmMessageBuffer::new();
|
||||
|
||||
#[wasm_bindgen(js_name = setSelectionMode)]
|
||||
pub fn set_selection_mode(mode: SelectionChannel) {
|
||||
wasm::write_message!(SELECT_MODE_BUF, mode);
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = setInteractionTransform)]
|
||||
pub fn set_interaction_transform(flags: u8) {
|
||||
wasm::write_message!(INTERACTION_TRANSFORM_BUF, InteractionTransform(flags));
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = setTransformSpace)]
|
||||
pub fn set_transform_space(space: TransformSpace) {
|
||||
wasm::write_message!(INTERACTION_SPACE_BUF, space);
|
||||
}
|
||||
|
||||
pub(super) fn update_selection_mode(mut selection_mode: ResMut<SelectionMode>) {
|
||||
wasm::read_buffer!(SELECT_MODE_BUF, mode => {
|
||||
selection_mode.0 = mode;
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn update_interaction_mode(mut interaction_mode: ResMut<InteractionMode>) {
|
||||
wasm::read_buffer!(INTERACTION_TRANSFORM_BUF, transform => {
|
||||
interaction_mode.transform = transform;
|
||||
});
|
||||
wasm::read_buffer!(INTERACTION_SPACE_BUF, space => {
|
||||
interaction_mode.space = space;
|
||||
});
|
||||
}
|
||||
}
|
||||
+22
-12
@@ -2,7 +2,13 @@
|
||||
|
||||
use bevy::prelude::*;
|
||||
use input::StudioInputPlugin;
|
||||
use orbit_cam::{CameraMotionSystem, OrbitCam, OrbitCamPlugin};
|
||||
use interaction::InteractionPlugin;
|
||||
#[rustfmt::skip]
|
||||
use orbit_cam::{
|
||||
// CameraMotionSystem,
|
||||
// OrbitCam,
|
||||
OrbitCamPlugin,
|
||||
};
|
||||
use skybox::SkyboxPlugin;
|
||||
use test_scene::TestScenePlugin;
|
||||
use ui::UiLayerPlugin;
|
||||
@@ -10,11 +16,14 @@ use viewport::ViewportSize;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod input;
|
||||
mod interaction;
|
||||
mod orbit_cam;
|
||||
mod skybox;
|
||||
mod test_scene;
|
||||
mod ui;
|
||||
mod viewport;
|
||||
// #[cfg(target_arch = "wasm32")]
|
||||
mod wasm;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn init(viewport_size: ViewportSize) {
|
||||
@@ -36,24 +45,25 @@ pub fn init(viewport_size: ViewportSize) {
|
||||
..default()
|
||||
}),
|
||||
StudioInputPlugin,
|
||||
InteractionPlugin,
|
||||
OrbitCamPlugin,
|
||||
TestScenePlugin,
|
||||
SkyboxPlugin,
|
||||
UiLayerPlugin,
|
||||
))
|
||||
.add_systems(Update, draw_world_axes.after(CameraMotionSystem))
|
||||
// .add_systems(Update, draw_world_axes.after(CameraMotionSystem))
|
||||
.run();
|
||||
}
|
||||
|
||||
fn draw_world_axes(mut gizmos: Gizmos, q: Query<&OrbitCam>) {
|
||||
let &OrbitCam { focus, radius, .. } = q.single();
|
||||
// fn draw_world_axes(mut gizmos: Gizmos, q: Query<&OrbitCam>) {
|
||||
// let &OrbitCam { focus, radius, .. } = q.single();
|
||||
|
||||
let mut draw_axis = |direction: Vec3, color: Color| {
|
||||
let end = focus + direction * radius / 15.;
|
||||
gizmos.line(focus, end, color);
|
||||
};
|
||||
// let mut draw_axis = |direction: Vec3, color: Color| {
|
||||
// let end = focus + direction * radius / 15.;
|
||||
// gizmos.line(focus, end, color);
|
||||
// };
|
||||
|
||||
draw_axis(Vec3::X, Color::RED);
|
||||
draw_axis(Vec3::Y, Color::GREEN);
|
||||
draw_axis(Vec3::Z, Color::BLUE);
|
||||
}
|
||||
// draw_axis(Vec3::X, Color::RED);
|
||||
// draw_axis(Vec3::Y, Color::GREEN);
|
||||
// draw_axis(Vec3::Z, Color::BLUE);
|
||||
// }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use bevy::math::vec3;
|
||||
#[rustfmt::skip]
|
||||
use bevy::{
|
||||
pbr::NotShadowCaster,
|
||||
@@ -6,7 +7,10 @@ use bevy::{
|
||||
render::render_resource::{AsBindGroup, ShaderRef},
|
||||
};
|
||||
|
||||
use crate::orbit_cam::{CameraMotionSystem, OrbitCam};
|
||||
use crate::{
|
||||
interaction::Selected,
|
||||
orbit_cam::{CameraMotionSystem, OrbitCam},
|
||||
};
|
||||
|
||||
pub struct TestScenePlugin;
|
||||
|
||||
@@ -15,6 +19,7 @@ impl Plugin for TestScenePlugin {
|
||||
app.insert_resource(ClearColor(Color::hsl(0.0, 0.0, 0.25)))
|
||||
.add_plugins(MaterialPlugin::<ProceduralGridMaterial>::default())
|
||||
.add_systems(Startup, spawn_scene)
|
||||
.add_systems(Update, right_round_round_round)
|
||||
.add_systems(PostUpdate, move_plane_with_camera.after(CameraMotionSystem));
|
||||
}
|
||||
}
|
||||
@@ -22,6 +27,9 @@ impl Plugin for TestScenePlugin {
|
||||
#[derive(Component)]
|
||||
struct WorldGridPlane;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Spin(Vec3); // TODO: Debug
|
||||
|
||||
fn spawn_scene(
|
||||
mut cmd: Commands,
|
||||
assets: Res<AssetServer>,
|
||||
@@ -29,10 +37,18 @@ fn spawn_scene(
|
||||
mut mat_proc_grid: ResMut<Assets<ProceduralGridMaterial>>,
|
||||
) {
|
||||
// Skeletal mesh
|
||||
cmd.spawn(SceneBundle {
|
||||
scene: assets.load("gltf/base_human_male.gltf#Scene0"),
|
||||
..default()
|
||||
});
|
||||
cmd.spawn((SpatialBundle::default(), Spin(Vec3::Y * 0.5)))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
SceneBundle {
|
||||
scene: assets.load("gltf/base_human_male.gltf#Scene0"),
|
||||
transform: Transform::from_translation(vec3(0., 0., 2.5)),
|
||||
..default()
|
||||
},
|
||||
Selected,
|
||||
Spin(vec3(0., -1.5, 1.)),
|
||||
));
|
||||
});
|
||||
|
||||
// Plane
|
||||
let plane = meshes.add(Mesh::from(shape::Plane {
|
||||
@@ -79,6 +95,17 @@ fn move_plane_with_camera(
|
||||
}
|
||||
}
|
||||
|
||||
fn right_round_round_round(mut q_spin: Query<(&mut Transform, &Spin)>, time: Res<Time>) {
|
||||
let dt = time.delta_seconds();
|
||||
|
||||
for (mut xform, spin) in q_spin.iter_mut() {
|
||||
let speed = spin.0.length();
|
||||
let axis = spin.0 / speed;
|
||||
|
||||
xform.rotate_local_axis(axis, std::f32::consts::PI * speed * dt);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(AsBindGroup, Clone, TypePath, TypeUuid)]
|
||||
#[uuid = "CE331A13-F247-4F5B-A75E-670B2BD5776A"]
|
||||
struct ProceduralGridMaterial {}
|
||||
|
||||
+8
-15
@@ -45,24 +45,20 @@ impl fmt::Debug for ViewportSize {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
// #[cfg(target_arch = "wasm32")]
|
||||
pub mod wasm {
|
||||
use std::{cell::RefCell, sync::OnceLock};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use parking_lot::ReentrantMutex;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::wasm::{self, WasmMessageBuffer};
|
||||
|
||||
use super::ViewportSize;
|
||||
|
||||
static RESIZE_BUF: OnceLock<ReentrantMutex<RefCell<Option<ViewportSize>>>> = OnceLock::new();
|
||||
static RESIZE_BUF: WasmMessageBuffer<ViewportSize> = WasmMessageBuffer::new();
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn resize(viewport_size: ViewportSize) {
|
||||
let buffer = RESIZE_BUF.get_or_init(|| ReentrantMutex::new(RefCell::new(None)));
|
||||
if let Some(lock) = buffer.try_lock() {
|
||||
*lock.borrow_mut() = Some(viewport_size);
|
||||
}
|
||||
wasm::write_message!(RESIZE_BUF, viewport_size);
|
||||
}
|
||||
|
||||
pub struct ViewportPlugin;
|
||||
@@ -89,11 +85,8 @@ pub mod wasm {
|
||||
}
|
||||
|
||||
fn dispatch_resize_events(mut events: EventWriter<ViewportResizeEvent>) {
|
||||
let buffer = RESIZE_BUF.get_or_init(|| ReentrantMutex::new(RefCell::new(None)));
|
||||
if let Some(lock) = buffer.try_lock() {
|
||||
if let Some(resize) = lock.borrow_mut().take() {
|
||||
events.send(ViewportResizeEvent(resize));
|
||||
}
|
||||
}
|
||||
wasm::read_buffer!(RESIZE_BUF, resize => {
|
||||
events.send(ViewportResizeEvent(resize));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
use std::{cell::RefCell, sync::OnceLock};
|
||||
|
||||
use parking_lot::ReentrantMutex;
|
||||
|
||||
pub(crate) type WasmMessageBuffer<T> = OnceLock<ReentrantMutex<RefCell<Option<T>>>>;
|
||||
|
||||
macro_rules! get_buffer {
|
||||
($buffer:ident) => {
|
||||
$buffer.get_or_init(|| {
|
||||
::parking_lot::ReentrantMutex::new(::std::cell::RefCell::new(
|
||||
::core::option::Option::None,
|
||||
))
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! write_message {
|
||||
($buffer:ident, $expr:expr) => {{
|
||||
let buffer = crate::wasm::get_buffer!($buffer);
|
||||
if let Some(lock) = buffer.try_lock() {
|
||||
*lock.borrow_mut() = Some($expr);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! read_buffer {
|
||||
($buffer:ident, $msg:ident => $stmt:stmt) => {{
|
||||
let buffer = crate::wasm::get_buffer!($buffer);
|
||||
if let Some(lock) = buffer.try_lock() {
|
||||
if let Some($msg) = lock.borrow_mut().take() {
|
||||
$stmt
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub(crate) use get_buffer;
|
||||
pub(crate) use read_buffer;
|
||||
pub(crate) use write_message;
|
||||
Reference in New Issue
Block a user