Compare commits
No commits in common. "e56f92a4ac32d96a84c5528f08448c55d6efbc99" and "e520eb07c5a050029567f83bc91582809d9a962d" have entirely different histories.
e56f92a4ac
...
e520eb07c5
|
|
@ -32,7 +32,6 @@
|
||||||
"eslint-plugin-react-hooks": "^7.1.1",
|
"eslint-plugin-react-hooks": "^7.1.1",
|
||||||
"eslint-plugin-react-refresh": "^0.5.2",
|
"eslint-plugin-react-refresh": "^0.5.2",
|
||||||
"globals": "^17.6.0",
|
"globals": "^17.6.0",
|
||||||
"sass": "^1.100.0",
|
|
||||||
"typescript": "~6.0.2",
|
"typescript": "~6.0.2",
|
||||||
"typescript-eslint": "^8.59.2",
|
"typescript-eslint": "^8.59.2",
|
||||||
"vite": "^8.0.12"
|
"vite": "^8.0.12"
|
||||||
|
|
|
||||||
201
pnpm-lock.yaml
201
pnpm-lock.yaml
|
|
@ -56,7 +56,7 @@ importers:
|
||||||
version: 19.2.3(@types/react@19.2.15)
|
version: 19.2.3(@types/react@19.2.15)
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: ^6.0.1
|
specifier: ^6.0.1
|
||||||
version: 6.0.2(vite@8.0.14(@types/node@24.12.4)(sass@1.100.0))
|
version: 6.0.2(vite@8.0.14(@types/node@24.12.4))
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^10.3.0
|
specifier: ^10.3.0
|
||||||
version: 10.4.1
|
version: 10.4.1
|
||||||
|
|
@ -69,9 +69,6 @@ importers:
|
||||||
globals:
|
globals:
|
||||||
specifier: ^17.6.0
|
specifier: ^17.6.0
|
||||||
version: 17.6.0
|
version: 17.6.0
|
||||||
sass:
|
|
||||||
specifier: ^1.100.0
|
|
||||||
version: 1.100.0
|
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ~6.0.2
|
specifier: ~6.0.2
|
||||||
version: 6.0.3
|
version: 6.0.3
|
||||||
|
|
@ -80,7 +77,7 @@ importers:
|
||||||
version: 8.60.0(eslint@10.4.1)(typescript@6.0.3)
|
version: 8.60.0(eslint@10.4.1)(typescript@6.0.3)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^8.0.12
|
specifier: ^8.0.12
|
||||||
version: 8.0.14(@types/node@24.12.4)(sass@1.100.0)
|
version: 8.0.14(@types/node@24.12.4)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
|
@ -259,94 +256,6 @@ packages:
|
||||||
'@oxc-project/types@0.132.0':
|
'@oxc-project/types@0.132.0':
|
||||||
resolution: {integrity: sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==}
|
resolution: {integrity: sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==}
|
||||||
|
|
||||||
'@parcel/watcher-android-arm64@2.5.6':
|
|
||||||
resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [android]
|
|
||||||
|
|
||||||
'@parcel/watcher-darwin-arm64@2.5.6':
|
|
||||||
resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
'@parcel/watcher-darwin-x64@2.5.6':
|
|
||||||
resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
'@parcel/watcher-freebsd-x64@2.5.6':
|
|
||||||
resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [freebsd]
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm-glibc@2.5.6':
|
|
||||||
resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm-musl@2.5.6':
|
|
||||||
resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm64-glibc@2.5.6':
|
|
||||||
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm64-musl@2.5.6':
|
|
||||||
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-x64-glibc@2.5.6':
|
|
||||||
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-x64-musl@2.5.6':
|
|
||||||
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@parcel/watcher-win32-arm64@2.5.6':
|
|
||||||
resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@parcel/watcher-win32-ia32@2.5.6':
|
|
||||||
resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [ia32]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@parcel/watcher-win32-x64@2.5.6':
|
|
||||||
resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@parcel/watcher@2.5.6':
|
|
||||||
resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==}
|
|
||||||
engines: {node: '>= 10.0.0'}
|
|
||||||
|
|
||||||
'@react-three/drei@10.7.7':
|
'@react-three/drei@10.7.7':
|
||||||
resolution: {integrity: sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==}
|
resolution: {integrity: sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -656,10 +565,6 @@ packages:
|
||||||
caniuse-lite@1.0.30001793:
|
caniuse-lite@1.0.30001793:
|
||||||
resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
|
resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
|
||||||
|
|
||||||
chokidar@5.0.0:
|
|
||||||
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
|
|
||||||
engines: {node: '>= 20.19.0'}
|
|
||||||
|
|
||||||
convert-source-map@2.0.0:
|
convert-source-map@2.0.0:
|
||||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||||
|
|
||||||
|
|
@ -843,9 +748,6 @@ packages:
|
||||||
immediate@3.0.6:
|
immediate@3.0.6:
|
||||||
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
||||||
|
|
||||||
immutable@5.1.6:
|
|
||||||
resolution: {integrity: sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==}
|
|
||||||
|
|
||||||
imurmurhash@0.1.4:
|
imurmurhash@0.1.4:
|
||||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
|
|
@ -1031,9 +933,6 @@ packages:
|
||||||
natural-compare@1.4.0:
|
natural-compare@1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
node-addon-api@7.1.1:
|
|
||||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
|
||||||
|
|
||||||
node-releases@2.0.46:
|
node-releases@2.0.46:
|
||||||
resolution: {integrity: sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==}
|
resolution: {integrity: sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -1172,10 +1071,6 @@ packages:
|
||||||
resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==}
|
resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
readdirp@5.0.0:
|
|
||||||
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
|
|
||||||
engines: {node: '>= 20.19.0'}
|
|
||||||
|
|
||||||
require-from-string@2.0.2:
|
require-from-string@2.0.2:
|
||||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -1185,11 +1080,6 @@ packages:
|
||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
sass@1.100.0:
|
|
||||||
resolution: {integrity: sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==}
|
|
||||||
engines: {node: '>=20.19.0'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
scheduler@0.27.0:
|
scheduler@0.27.0:
|
||||||
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||||
|
|
||||||
|
|
@ -1625,67 +1515,6 @@ snapshots:
|
||||||
|
|
||||||
'@oxc-project/types@0.132.0': {}
|
'@oxc-project/types@0.132.0': {}
|
||||||
|
|
||||||
'@parcel/watcher-android-arm64@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-darwin-arm64@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-darwin-x64@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-freebsd-x64@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm-glibc@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm-musl@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm64-glibc@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-arm64-musl@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-x64-glibc@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-linux-x64-musl@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-win32-arm64@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-win32-ia32@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher-win32-x64@2.5.6':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@parcel/watcher@2.5.6':
|
|
||||||
dependencies:
|
|
||||||
detect-libc: 2.1.2
|
|
||||||
is-glob: 4.0.3
|
|
||||||
node-addon-api: 7.1.1
|
|
||||||
picomatch: 4.0.4
|
|
||||||
optionalDependencies:
|
|
||||||
'@parcel/watcher-android-arm64': 2.5.6
|
|
||||||
'@parcel/watcher-darwin-arm64': 2.5.6
|
|
||||||
'@parcel/watcher-darwin-x64': 2.5.6
|
|
||||||
'@parcel/watcher-freebsd-x64': 2.5.6
|
|
||||||
'@parcel/watcher-linux-arm-glibc': 2.5.6
|
|
||||||
'@parcel/watcher-linux-arm-musl': 2.5.6
|
|
||||||
'@parcel/watcher-linux-arm64-glibc': 2.5.6
|
|
||||||
'@parcel/watcher-linux-arm64-musl': 2.5.6
|
|
||||||
'@parcel/watcher-linux-x64-glibc': 2.5.6
|
|
||||||
'@parcel/watcher-linux-x64-musl': 2.5.6
|
|
||||||
'@parcel/watcher-win32-arm64': 2.5.6
|
|
||||||
'@parcel/watcher-win32-ia32': 2.5.6
|
|
||||||
'@parcel/watcher-win32-x64': 2.5.6
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@react-three/drei@10.7.7(@react-three/fiber@9.6.1(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(three@0.184.0))(@types/react@19.2.15)(@types/three@0.184.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(three@0.184.0)':
|
'@react-three/drei@10.7.7(@react-three/fiber@9.6.1(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(three@0.184.0))(@types/react@19.2.15)(@types/three@0.184.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(three@0.184.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.29.7
|
'@babel/runtime': 7.29.7
|
||||||
|
|
@ -1934,10 +1763,10 @@ snapshots:
|
||||||
'@use-gesture/core': 10.3.1
|
'@use-gesture/core': 10.3.1
|
||||||
react: 19.2.6
|
react: 19.2.6
|
||||||
|
|
||||||
'@vitejs/plugin-react@6.0.2(vite@8.0.14(@types/node@24.12.4)(sass@1.100.0))':
|
'@vitejs/plugin-react@6.0.2(vite@8.0.14(@types/node@24.12.4))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rolldown/pluginutils': 1.0.1
|
'@rolldown/pluginutils': 1.0.1
|
||||||
vite: 8.0.14(@types/node@24.12.4)(sass@1.100.0)
|
vite: 8.0.14(@types/node@24.12.4)
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.16.0):
|
acorn-jsx@5.3.2(acorn@8.16.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -1985,10 +1814,6 @@ snapshots:
|
||||||
|
|
||||||
caniuse-lite@1.0.30001793: {}
|
caniuse-lite@1.0.30001793: {}
|
||||||
|
|
||||||
chokidar@5.0.0:
|
|
||||||
dependencies:
|
|
||||||
readdirp: 5.0.0
|
|
||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
|
|
||||||
cross-env@7.0.3:
|
cross-env@7.0.3:
|
||||||
|
|
@ -2161,8 +1986,6 @@ snapshots:
|
||||||
|
|
||||||
immediate@3.0.6: {}
|
immediate@3.0.6: {}
|
||||||
|
|
||||||
immutable@5.1.6: {}
|
|
||||||
|
|
||||||
imurmurhash@0.1.4: {}
|
imurmurhash@0.1.4: {}
|
||||||
|
|
||||||
install@0.13.0: {}
|
install@0.13.0: {}
|
||||||
|
|
@ -2297,9 +2120,6 @@ snapshots:
|
||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
node-addon-api@7.1.1:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
node-releases@2.0.46: {}
|
node-releases@2.0.46: {}
|
||||||
|
|
||||||
npm@11.16.0: {}
|
npm@11.16.0: {}
|
||||||
|
|
@ -2359,8 +2179,6 @@ snapshots:
|
||||||
|
|
||||||
react@19.2.6: {}
|
react@19.2.6: {}
|
||||||
|
|
||||||
readdirp@5.0.0: {}
|
|
||||||
|
|
||||||
require-from-string@2.0.2: {}
|
require-from-string@2.0.2: {}
|
||||||
|
|
||||||
rolldown@1.0.2:
|
rolldown@1.0.2:
|
||||||
|
|
@ -2384,14 +2202,6 @@ snapshots:
|
||||||
'@rolldown/binding-win32-arm64-msvc': 1.0.2
|
'@rolldown/binding-win32-arm64-msvc': 1.0.2
|
||||||
'@rolldown/binding-win32-x64-msvc': 1.0.2
|
'@rolldown/binding-win32-x64-msvc': 1.0.2
|
||||||
|
|
||||||
sass@1.100.0:
|
|
||||||
dependencies:
|
|
||||||
chokidar: 5.0.0
|
|
||||||
immutable: 5.1.6
|
|
||||||
source-map-js: 1.2.1
|
|
||||||
optionalDependencies:
|
|
||||||
'@parcel/watcher': 2.5.6
|
|
||||||
|
|
||||||
scheduler@0.27.0: {}
|
scheduler@0.27.0: {}
|
||||||
|
|
||||||
semver@6.3.1: {}
|
semver@6.3.1: {}
|
||||||
|
|
@ -2504,7 +2314,7 @@ snapshots:
|
||||||
|
|
||||||
uuid@14.0.0: {}
|
uuid@14.0.0: {}
|
||||||
|
|
||||||
vite@8.0.14(@types/node@24.12.4)(sass@1.100.0):
|
vite@8.0.14(@types/node@24.12.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
lightningcss: 1.32.0
|
lightningcss: 1.32.0
|
||||||
picomatch: 4.0.4
|
picomatch: 4.0.4
|
||||||
|
|
@ -2514,7 +2324,6 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 24.12.4
|
'@types/node': 24.12.4
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
sass: 1.100.0
|
|
||||||
|
|
||||||
webgl-constants@1.1.1: {}
|
webgl-constants@1.1.1: {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
allowBuilds:
|
|
||||||
'@parcel/watcher': set this to true or false
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { ThreeView } from './components/ThreeView';
|
import { ThreeView } from './components/ThreeView';
|
||||||
import './App.scss';
|
import './App.css';
|
||||||
import { Toolbar } from './components/Toolbar';
|
import { Toolbar } from './components/Toolbar';
|
||||||
|
|
||||||
export const App = function () {
|
export const App = function () {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ThreeView />
|
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
|
<ThreeView />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import type { Character, Scene } from "../types";
|
import { state } from "../state";
|
||||||
|
|
||||||
export const CharacterView = observer(function ({ character }: { character: Character }) {
|
export const CharacterView = observer(function () {
|
||||||
|
const character = state.world.currentScene.character;
|
||||||
|
|
||||||
return <mesh position={character.position} rotation={character.look}>
|
return <mesh position={character.position} rotation={character.look}>
|
||||||
<boxGeometry args={[0.8, 0.8, 0.8]} />
|
<boxGeometry args={[0.8, 0.8, 0.8]} />
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import { observer } from "mobx-react-lite";
|
|
||||||
import { SceneView } from "./SceneView";
|
|
||||||
import { state } from "../state";
|
|
||||||
import { useFrame } from "@react-three/fiber";
|
|
||||||
|
|
||||||
export const GameView = observer(function () {
|
|
||||||
const game = state.game;
|
|
||||||
|
|
||||||
useFrame((_, delta) => {
|
|
||||||
state.game?.tick(delta);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!game)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return <SceneView scene={game.scene} />;
|
|
||||||
});
|
|
||||||
|
|
@ -5,7 +5,7 @@ import type { Group } from "three";
|
||||||
import { Edges, TransformControls } from "@react-three/drei";
|
import { Edges, TransformControls } from "@react-three/drei";
|
||||||
import type { ThreeEvent } from "@react-three/fiber";
|
import type { ThreeEvent } from "@react-three/fiber";
|
||||||
import { state } from "../state";
|
import { state } from "../state";
|
||||||
import { nextSelectionEditMode } from "../state/worldEditorState";
|
import { nextSelectionEditMode } from "../state/worldEditor";
|
||||||
import type { R3 } from "../types/3d";
|
import type { R3 } from "../types/3d";
|
||||||
|
|
||||||
type ObjectViewProps = {
|
type ObjectViewProps = {
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
import { useLayoutEffect, useRef } from 'react';
|
|
||||||
import type React from 'react';
|
|
||||||
import { useThree } from '@react-three/fiber';
|
|
||||||
import { OrbitControls } from '@react-three/drei';
|
|
||||||
import { observer } from 'mobx-react-lite';
|
|
||||||
import { state } from '../state';
|
|
||||||
import { SceneView } from './SceneView';
|
|
||||||
import type { Pos3 } from '../types/3d';
|
|
||||||
|
|
||||||
const CameraSync = observer(function ({ camera }: { camera: Pos3 }) {
|
|
||||||
const { camera: threeCamera } = useThree();
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
threeCamera.position.set(camera.position[0], camera.position[1], camera.position[2]);
|
|
||||||
threeCamera.rotation.set(camera.look[0], camera.look[1], camera.look[2]);
|
|
||||||
threeCamera.updateProjectionMatrix();
|
|
||||||
});
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SceneEditorView = observer(function () {
|
|
||||||
const controlsRef = useRef<React.ComponentRef<typeof OrbitControls>>(null);
|
|
||||||
|
|
||||||
const handleEnd = () => {
|
|
||||||
const controls = controlsRef.current;
|
|
||||||
if (!controls)
|
|
||||||
return;
|
|
||||||
const [x, y, z] = controls.object.rotation.toArray();
|
|
||||||
state.worldEditor.setCamera({
|
|
||||||
position: controls.object.position.toArray(),
|
|
||||||
look: [x, y, z],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (<>
|
|
||||||
<OrbitControls
|
|
||||||
ref={controlsRef}
|
|
||||||
enabled={!state.worldEditor.isDragging}
|
|
||||||
onEnd={handleEnd}
|
|
||||||
makeDefault
|
|
||||||
enableDamping={false}
|
|
||||||
/>
|
|
||||||
<CameraSync camera={state.worldEditor.camera} />
|
|
||||||
<SceneView scene={state.worldEditor.scene} />
|
|
||||||
</>);
|
|
||||||
});
|
|
||||||
|
|
@ -13,6 +13,6 @@ export const SceneView = observer(function ({ scene }: SceneViewProps) {
|
||||||
<directionalLight position={[5, 5, 5]} intensity={1} />
|
<directionalLight position={[5, 5, 5]} intensity={1} />
|
||||||
{Object.values(scene.objects).map((obj) =>
|
{Object.values(scene.objects).map((obj) =>
|
||||||
<ObjectView key={obj.id} object={obj} />)}
|
<ObjectView key={obj.id} object={obj} />)}
|
||||||
<CharacterView character={scene.character} />
|
<CharacterView />
|
||||||
</>);
|
</>);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,17 @@
|
||||||
import { Canvas } from '@react-three/fiber';
|
import { Canvas } from '@react-three/fiber';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
import { state } from '../state';
|
import { state } from '../state';
|
||||||
import { GameView } from './GameView';
|
import { WorldView } from './WorldView';
|
||||||
import { SceneEditorView } from './SceneEditorView';
|
|
||||||
|
|
||||||
const IconStop = () => <svg viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" fill="currentColor" /></svg>;
|
|
||||||
const IconPause = () => <svg viewBox="0 0 14 14"><rect x="2" y="2" width="4" height="10" fill="currentColor" /><rect x="8" y="2" width="4" height="10" fill="currentColor" /></svg >;
|
|
||||||
const IconPlay = () => <svg viewBox="0 0 14 14"><polygon points="3,1 13,7 3,13" fill="currentColor" /></svg>;
|
|
||||||
|
|
||||||
export const ThreeView = observer(function () {
|
export const ThreeView = observer(function () {
|
||||||
const isGame = state.isGamePlaying;
|
|
||||||
return (
|
return (
|
||||||
<div style={{ position: 'relative', width: '800px', height: '600px', border: '1px solid #333', borderRadius: '8px', overflow: 'hidden' }}>
|
<div style={{ width: '800px', height: '600px', border: '1px solid #333', borderRadius: '8px', overflow: 'hidden' }}>
|
||||||
<Canvas
|
<Canvas
|
||||||
// camera={state.world.character.camera}
|
camera={state.world.character.camera}
|
||||||
onPointerMissed={() => state.worldEditor.resetSelectedObject()}
|
onPointerMissed={() => state.worldEditor.resetSelectedObject()}
|
||||||
>
|
>
|
||||||
{isGame ? <GameView /> : <SceneEditorView />}
|
<WorldView />
|
||||||
</Canvas>
|
</Canvas>
|
||||||
<div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 4 }}>
|
|
||||||
{
|
|
||||||
state.game
|
|
||||||
? <>
|
|
||||||
<button onClick={() => state.game!.stop()}><IconStop /></button>
|
|
||||||
{
|
|
||||||
state.game!.isPaused
|
|
||||||
? <button onClick={() => state.game!.resume()}><IconPlay /></button>
|
|
||||||
: <button onClick={() => state.game!.pause()}><IconPause /></button>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
: <button onClick={() => state.world.play()}><IconPlay /></button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,18 @@ export const Toolbar = observer(function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className="toolbar">
|
return <div className="toolbar">
|
||||||
|
{state.worldEditor.isEnabled && <div>EDITOR MODE</div>}
|
||||||
|
{state.world.isPlaying
|
||||||
|
? <>
|
||||||
|
<button onClick={() => state.world.stop()}>Stop</button>
|
||||||
|
{
|
||||||
|
(state.world.data.state as RunningGameState).paused
|
||||||
|
? <button onClick={() => state.world.play()}>Play</button>
|
||||||
|
: <button onClick={() => state.world.pause()}>Pause</button>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
: <button onClick={() => state.world.play()}>Play</button>
|
||||||
|
}
|
||||||
<button onClick={handleLoadMockWorld}>Load mock world</button>
|
<button onClick={handleLoadMockWorld}>Load mock world</button>
|
||||||
<button onClick={handleCloneTest1Object}>Clone test1</button>
|
<button onClick={handleCloneTest1Object}>Clone test1</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { useLayoutEffect, useRef } from 'react';
|
||||||
|
import type React from 'react';
|
||||||
|
import { useFrame, useThree } from '@react-three/fiber';
|
||||||
|
import { OrbitControls } from '@react-three/drei';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { state } from '../state';
|
||||||
|
import { SceneView } from './SceneView';
|
||||||
|
|
||||||
|
const CameraSync = observer(function () {
|
||||||
|
const { camera } = useThree();
|
||||||
|
const cam = state.world.currentCamera; // MobX tracks this; re-renders on change
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
camera.position.set(cam.position[0], cam.position[1], cam.position[2]);
|
||||||
|
camera.rotation.set(cam.look[0], cam.look[1], cam.look[2]);
|
||||||
|
camera.updateProjectionMatrix();
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const WorldView = observer(function () {
|
||||||
|
const world = state.world;
|
||||||
|
const controlsRef = useRef<React.ComponentRef<typeof OrbitControls>>(null);
|
||||||
|
|
||||||
|
useFrame((_, delta) => {
|
||||||
|
world.tick(delta);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleEnd = () => {
|
||||||
|
const controls = controlsRef.current;
|
||||||
|
if (!controls || world.isPlaying)
|
||||||
|
return;
|
||||||
|
const [x, y, z] = controls.object.rotation.toArray();
|
||||||
|
state.worldEditor.setCamera({
|
||||||
|
position: controls.object.position.toArray(),
|
||||||
|
look: [x, y, z],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
<OrbitControls
|
||||||
|
ref={controlsRef}
|
||||||
|
enabled={!world.isPlaying && !state.worldEditor.isDragging}
|
||||||
|
onEnd={handleEnd}
|
||||||
|
makeDefault
|
||||||
|
enableDamping={false}
|
||||||
|
/>
|
||||||
|
<CameraSync />
|
||||||
|
<SceneView scene={state.world.currentScene} />
|
||||||
|
</>)
|
||||||
|
});
|
||||||
|
|
@ -15,8 +15,7 @@
|
||||||
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
|
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
|
||||||
--mono: ui-monospace, Consolas, monospace;
|
--mono: ui-monospace, Consolas, monospace;
|
||||||
|
|
||||||
font: 16px/100% var(--sans);
|
font: 18px/145% var(--sans);
|
||||||
line-height: 1;
|
|
||||||
letter-spacing: 0.18px;
|
letter-spacing: 0.18px;
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
|
@ -25,6 +24,10 @@
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
|
|
@ -63,17 +66,46 @@ body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
h1,
|
||||||
fill: currentColor;
|
h2 {
|
||||||
display: inline-block;
|
font-family: var(--heading);
|
||||||
height: 1em;
|
font-weight: 500;
|
||||||
top: 0.125em;
|
color: var(--text-h);
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
h1 {
|
||||||
input,
|
font-size: 56px;
|
||||||
select,
|
letter-spacing: -1.68px;
|
||||||
textarea {
|
margin: 32px 0;
|
||||||
font: inherit;
|
@media (max-width: 1024px) {
|
||||||
|
font-size: 36px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 118%;
|
||||||
|
letter-spacing: -0.24px;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
.counter {
|
||||||
|
font-family: var(--mono);
|
||||||
|
display: inline-flex;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--text-h);
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 135%;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: var(--code-bg);
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { StrictMode } from 'react'
|
import { StrictMode } from 'react'
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import { App } from './App.tsx'
|
import { App } from './App.tsx'
|
||||||
import './index.scss'
|
import './index.css'
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { makeAutoObservable } from "mobx";
|
||||||
|
import type { WorldState } from "./world";
|
||||||
|
import type { CameraProps } from "@react-three/fiber";
|
||||||
|
|
||||||
|
export class CharacterState {
|
||||||
|
private readonly world: WorldState;
|
||||||
|
|
||||||
|
constructor(world: WorldState) {
|
||||||
|
this.world = world;
|
||||||
|
makeAutoObservable(
|
||||||
|
this,
|
||||||
|
{
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get camera(): CameraProps {
|
||||||
|
const cam = this.world.currentCamera;
|
||||||
|
return {
|
||||||
|
position: cam.position,
|
||||||
|
fov: 50,
|
||||||
|
rotation: cam.look,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
import { makeAutoObservable } from "mobx";
|
|
||||||
import type { WorldState } from "./worldState";
|
|
||||||
import type { RunningGameState, Scene } from "../types";
|
|
||||||
import { clone } from "../utils";
|
|
||||||
import { state } from "./rootState";
|
|
||||||
import type { Pos3 } from "../types/3d";
|
|
||||||
import type { CameraProps } from "@react-three/fiber";
|
|
||||||
|
|
||||||
export class GameState {
|
|
||||||
private readonly world: WorldState;
|
|
||||||
|
|
||||||
constructor(world: WorldState) {
|
|
||||||
this.world = world;
|
|
||||||
makeAutoObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get state(): RunningGameState {
|
|
||||||
return this.world.data.state as RunningGameState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isPaused(): boolean {
|
|
||||||
return this.state.paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get scene(): Scene {
|
|
||||||
return this.state.scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get camera(): Pos3 {
|
|
||||||
return this.scene.character;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get cameraAsThree(): CameraProps {
|
|
||||||
const cam = this.camera;
|
|
||||||
return {
|
|
||||||
position: cam.position,
|
|
||||||
fov: 50,
|
|
||||||
rotation: cam.look,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public resume(): void {
|
|
||||||
const state = clone(this.world.data.state) as RunningGameState;
|
|
||||||
state.paused = false;
|
|
||||||
this.world.data.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public pause(): void {
|
|
||||||
const state = clone(this.world.data.state) as RunningGameState;
|
|
||||||
state.paused = true;
|
|
||||||
this.world.data.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public stop(): void {
|
|
||||||
this.world.data.state = { playing: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
public tick(deltaTime: number): void {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
export * from './rootState';
|
export * from './root';
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { makeAutoObservable } from "mobx";
|
import { makeAutoObservable } from "mobx";
|
||||||
import { WorldState } from "./worldState";
|
import { WorldState } from "./world";
|
||||||
import { WorldEditorState } from "./worldEditorState";
|
import { WorldEditorState } from "./worldEditor";
|
||||||
import { GameState } from "./gameState";
|
|
||||||
|
|
||||||
export class RootState {
|
export class RootState {
|
||||||
public readonly world = new WorldState();
|
public readonly world = new WorldState();
|
||||||
|
|
@ -17,15 +16,6 @@ export class RootState {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isGamePlaying(): boolean {
|
|
||||||
return this.world.data.state.playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get game(): GameState | undefined {
|
|
||||||
if (this.isGamePlaying)
|
|
||||||
return new GameState(this.world);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const state = new RootState();
|
export const state = new RootState();
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
import { makeAutoObservable } from "mobx";
|
import { makeAutoObservable } from "mobx";
|
||||||
import { WorldFactory } from "../model/worldFactory";
|
import { WorldFactory } from "../model/worldFactory";
|
||||||
import type { ObjectType, World } from "../types";
|
import type { ObjectType, RunningGameState, Scene, World } from "../types";
|
||||||
|
import { CharacterState } from "./character";
|
||||||
|
import type { Pos3 } from "../types/3d";
|
||||||
|
import { clone } from "../utils";
|
||||||
import type { VoxelType } from "../types/voxel";
|
import type { VoxelType } from "../types/voxel";
|
||||||
import { state } from "./rootState";
|
import { state } from "./root";
|
||||||
import { DEFAULT_VOXEL_TYPES } from "../model/defaultVoxelTypes";
|
import { DEFAULT_VOXEL_TYPES } from "../model/defaultVoxelTypes";
|
||||||
import { wolf } from "../model/objectPrefabs/wolf";
|
import { wolf } from "../model/objectPrefabs/wolf";
|
||||||
import { clone } from "../utils";
|
|
||||||
|
|
||||||
export class WorldState {
|
export class WorldState {
|
||||||
public data: World = WorldFactory.create();
|
public data: World = WorldFactory.create();
|
||||||
|
|
||||||
|
public character = new CharacterState(this);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
@ -71,17 +75,35 @@ export class WorldState {
|
||||||
WorldFactory.save(this.data);
|
WorldFactory.save(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getObjectTypeById(id: string): ObjectType | undefined {
|
public get isPlaying(): boolean {
|
||||||
return this.data.objectTypes[id];
|
return this.data.state.playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVoxelTypeById(id: string): VoxelType | undefined {
|
public get currentScene(): Scene {
|
||||||
return this.data.voxelTypes[id];
|
return this.isPlaying
|
||||||
|
? (this.data.state as RunningGameState).scene
|
||||||
|
: this.data.initialScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get currentCamera(): Pos3 {
|
||||||
|
return this.isPlaying
|
||||||
|
? (this.data.state as RunningGameState).scene.character
|
||||||
|
: this.data.editorCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
public tick(_delta: number) {
|
||||||
|
if (!this.isPlaying)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
public play(): void {
|
public play(): void {
|
||||||
if (state.game)
|
if (this.isPlaying) {
|
||||||
state.game.resume();
|
const state = clone(this.data.state) as RunningGameState;
|
||||||
|
state.paused = false;
|
||||||
|
this.data.state = state;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
this.data.state = {
|
this.data.state = {
|
||||||
playing: true,
|
playing: true,
|
||||||
|
|
@ -89,7 +111,29 @@ export class WorldState {
|
||||||
time: 0,
|
time: 0,
|
||||||
scene: clone(this.data.initialScene),
|
scene: clone(this.data.initialScene),
|
||||||
}
|
}
|
||||||
state.worldEditor.resetSelectedObject();
|
|
||||||
}
|
}
|
||||||
|
state.worldEditor.resetSelectedObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public pause(): void {
|
||||||
|
if (!this.isPlaying)
|
||||||
|
return;
|
||||||
|
const state = clone(this.data.state) as RunningGameState;
|
||||||
|
state.paused = true;
|
||||||
|
this.data.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public stop(): void {
|
||||||
|
if (!this.isPlaying)
|
||||||
|
return;
|
||||||
|
this.data.state = { playing: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
public getObjectTypeById(id: string): ObjectType | undefined {
|
||||||
|
return this.data.objectTypes[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getVoxelTypeById(id: string): VoxelType | undefined {
|
||||||
|
return this.data.voxelTypes[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import { makeAutoObservable } from "mobx";
|
import { makeAutoObservable } from "mobx";
|
||||||
import type { WorldState } from "./worldState";
|
import type { WorldState } from "./world";
|
||||||
import type { ObjectInstance, Scene, World } from "../types";
|
import type { ObjectInstance, Scene, World } from "../types";
|
||||||
import { createObjectInstance } from "../utils/object";
|
import { createObjectInstance } from "../utils/object";
|
||||||
import { randomId } from "../utils";
|
import { randomId } from "../utils";
|
||||||
import type { Pos3, R3, V3 } from "../types/3d";
|
import type { Pos3, R3, V3 } from "../types/3d";
|
||||||
import { state } from "./rootState";
|
|
||||||
|
|
||||||
export const SelectionEditModeEnum = [
|
export const SelectionEditModeEnum = [
|
||||||
'translate',
|
'translate',
|
||||||
|
|
@ -35,7 +34,7 @@ export class WorldEditorState {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isEnabled(): boolean {
|
public get isEnabled(): boolean {
|
||||||
return !state.isGamePlaying;
|
return !this.world.isPlaying;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setCamera(value: Pos3): void {
|
public setCamera(value: Pos3): void {
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
import type { Pos3 } from "./3d";
|
|
||||||
|
|
||||||
export type Character = Pos3 & {
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
import type { Pos3 } from "./3d";
|
||||||
|
|
||||||
|
export type CharacterState = Pos3 & {
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ export * from './scene';
|
||||||
export * from './world';
|
export * from './world';
|
||||||
export * from './gameRules';
|
export * from './gameRules';
|
||||||
export * from './gameState';
|
export * from './gameState';
|
||||||
export * from './character';
|
export * from './characterState';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { Character } from "./character";
|
import type { CharacterState } from "./characterState";
|
||||||
import type { ObjectInstance } from "./object";
|
import type { ObjectInstance } from "./object";
|
||||||
|
|
||||||
export type Scene = {
|
export type Scene = {
|
||||||
character: Character;
|
character: CharacterState;
|
||||||
objects: Record<string, ObjectInstance>;
|
objects: Record<string, ObjectInstance>;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue