Compare commits

..

5 Commits

9 changed files with 349 additions and 320 deletions

281
package-lock.json generated
View File

@ -1279,10 +1279,11 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@parcel/watcher": { "node_modules/@parcel/watcher": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz",
"integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==",
"dev": true, "dev": true,
"hasInstallScript": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@ -1299,24 +1300,25 @@
"url": "https://opencollective.com/parcel" "url": "https://opencollective.com/parcel"
}, },
"optionalDependencies": { "optionalDependencies": {
"@parcel/watcher-android-arm64": "2.4.1", "@parcel/watcher-android-arm64": "2.5.0",
"@parcel/watcher-darwin-arm64": "2.4.1", "@parcel/watcher-darwin-arm64": "2.5.0",
"@parcel/watcher-darwin-x64": "2.4.1", "@parcel/watcher-darwin-x64": "2.5.0",
"@parcel/watcher-freebsd-x64": "2.4.1", "@parcel/watcher-freebsd-x64": "2.5.0",
"@parcel/watcher-linux-arm-glibc": "2.4.1", "@parcel/watcher-linux-arm-glibc": "2.5.0",
"@parcel/watcher-linux-arm64-glibc": "2.4.1", "@parcel/watcher-linux-arm-musl": "2.5.0",
"@parcel/watcher-linux-arm64-musl": "2.4.1", "@parcel/watcher-linux-arm64-glibc": "2.5.0",
"@parcel/watcher-linux-x64-glibc": "2.4.1", "@parcel/watcher-linux-arm64-musl": "2.5.0",
"@parcel/watcher-linux-x64-musl": "2.4.1", "@parcel/watcher-linux-x64-glibc": "2.5.0",
"@parcel/watcher-win32-arm64": "2.4.1", "@parcel/watcher-linux-x64-musl": "2.5.0",
"@parcel/watcher-win32-ia32": "2.4.1", "@parcel/watcher-win32-arm64": "2.5.0",
"@parcel/watcher-win32-x64": "2.4.1" "@parcel/watcher-win32-ia32": "2.5.0",
"@parcel/watcher-win32-x64": "2.5.0"
} }
}, },
"node_modules/@parcel/watcher-android-arm64": { "node_modules/@parcel/watcher-android-arm64": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz",
"integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1335,9 +1337,9 @@
} }
}, },
"node_modules/@parcel/watcher-darwin-arm64": { "node_modules/@parcel/watcher-darwin-arm64": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz",
"integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1356,9 +1358,9 @@
} }
}, },
"node_modules/@parcel/watcher-darwin-x64": { "node_modules/@parcel/watcher-darwin-x64": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz",
"integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1377,9 +1379,9 @@
} }
}, },
"node_modules/@parcel/watcher-freebsd-x64": { "node_modules/@parcel/watcher-freebsd-x64": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz",
"integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1398,9 +1400,30 @@
} }
}, },
"node_modules/@parcel/watcher-linux-arm-glibc": { "node_modules/@parcel/watcher-linux-arm-glibc": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz",
"integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-musl": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz",
"integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1419,9 +1442,9 @@
} }
}, },
"node_modules/@parcel/watcher-linux-arm64-glibc": { "node_modules/@parcel/watcher-linux-arm64-glibc": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz",
"integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1440,9 +1463,9 @@
} }
}, },
"node_modules/@parcel/watcher-linux-arm64-musl": { "node_modules/@parcel/watcher-linux-arm64-musl": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz",
"integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1461,9 +1484,9 @@
} }
}, },
"node_modules/@parcel/watcher-linux-x64-glibc": { "node_modules/@parcel/watcher-linux-x64-glibc": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz",
"integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1482,9 +1505,9 @@
} }
}, },
"node_modules/@parcel/watcher-linux-x64-musl": { "node_modules/@parcel/watcher-linux-x64-musl": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz",
"integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1503,9 +1526,9 @@
} }
}, },
"node_modules/@parcel/watcher-win32-arm64": { "node_modules/@parcel/watcher-win32-arm64": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz",
"integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1524,9 +1547,9 @@
} }
}, },
"node_modules/@parcel/watcher-win32-ia32": { "node_modules/@parcel/watcher-win32-ia32": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz",
"integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -1545,9 +1568,9 @@
} }
}, },
"node_modules/@parcel/watcher-win32-x64": { "node_modules/@parcel/watcher-win32-x64": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz",
"integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1633,9 +1656,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz",
"integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==", "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1647,9 +1670,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz",
"integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==", "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1661,9 +1684,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz",
"integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==", "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1675,9 +1698,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz",
"integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==", "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1689,9 +1712,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz",
"integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==", "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1703,9 +1726,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz",
"integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==", "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1717,9 +1740,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz",
"integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==", "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1731,9 +1754,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz",
"integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==", "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1745,9 +1768,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz",
"integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==", "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1759,9 +1782,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz",
"integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==", "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1773,9 +1796,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz",
"integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==", "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -1787,9 +1810,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz",
"integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==", "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@ -1801,9 +1824,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz",
"integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==", "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@ -1815,9 +1838,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz",
"integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==", "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1829,9 +1852,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz",
"integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==", "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1843,9 +1866,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz",
"integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==", "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1857,9 +1880,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz",
"integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==", "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -1871,9 +1894,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz",
"integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==", "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -3598,9 +3621,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.50", "version": "1.5.51",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.51.tgz",
"integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", "integrity": "sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@ -6357,9 +6380,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.24.3", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.3.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz",
"integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==", "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -6373,24 +6396,24 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.24.3", "@rollup/rollup-android-arm-eabi": "4.24.4",
"@rollup/rollup-android-arm64": "4.24.3", "@rollup/rollup-android-arm64": "4.24.4",
"@rollup/rollup-darwin-arm64": "4.24.3", "@rollup/rollup-darwin-arm64": "4.24.4",
"@rollup/rollup-darwin-x64": "4.24.3", "@rollup/rollup-darwin-x64": "4.24.4",
"@rollup/rollup-freebsd-arm64": "4.24.3", "@rollup/rollup-freebsd-arm64": "4.24.4",
"@rollup/rollup-freebsd-x64": "4.24.3", "@rollup/rollup-freebsd-x64": "4.24.4",
"@rollup/rollup-linux-arm-gnueabihf": "4.24.3", "@rollup/rollup-linux-arm-gnueabihf": "4.24.4",
"@rollup/rollup-linux-arm-musleabihf": "4.24.3", "@rollup/rollup-linux-arm-musleabihf": "4.24.4",
"@rollup/rollup-linux-arm64-gnu": "4.24.3", "@rollup/rollup-linux-arm64-gnu": "4.24.4",
"@rollup/rollup-linux-arm64-musl": "4.24.3", "@rollup/rollup-linux-arm64-musl": "4.24.4",
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.3", "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4",
"@rollup/rollup-linux-riscv64-gnu": "4.24.3", "@rollup/rollup-linux-riscv64-gnu": "4.24.4",
"@rollup/rollup-linux-s390x-gnu": "4.24.3", "@rollup/rollup-linux-s390x-gnu": "4.24.4",
"@rollup/rollup-linux-x64-gnu": "4.24.3", "@rollup/rollup-linux-x64-gnu": "4.24.4",
"@rollup/rollup-linux-x64-musl": "4.24.3", "@rollup/rollup-linux-x64-musl": "4.24.4",
"@rollup/rollup-win32-arm64-msvc": "4.24.3", "@rollup/rollup-win32-arm64-msvc": "4.24.4",
"@rollup/rollup-win32-ia32-msvc": "4.24.3", "@rollup/rollup-win32-ia32-msvc": "4.24.4",
"@rollup/rollup-win32-x64-msvc": "4.24.3", "@rollup/rollup-win32-x64-msvc": "4.24.4",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },

View File

@ -1,9 +1,9 @@
<template> <template>
<ZoneTiles @tilemap:create="tileMap = $event" /> <ZoneTiles @tileMap:create="tileMap = $event" />
<ZoneObjects v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" /> <ZoneObjects v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
<ZoneEventTiles v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" /> <ZoneEventTiles v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
<Toolbar @save="save" /> <Toolbar @save="save" @clear="clear" />
<ZoneList /> <ZoneList />
<TileList /> <TileList />
@ -26,14 +26,24 @@ import ObjectList from '@/components/gameMaster/zoneEditor/partials/ObjectList.v
import ZoneSettings from '@/components/gameMaster/zoneEditor/partials/ZoneSettings.vue' import ZoneSettings from '@/components/gameMaster/zoneEditor/partials/ZoneSettings.vue'
import ZoneList from '@/components/gameMaster/zoneEditor/partials/ZoneList.vue' import ZoneList from '@/components/gameMaster/zoneEditor/partials/ZoneList.vue'
import TeleportModal from '@/components/gameMaster/zoneEditor/partials/TeleportModal.vue' import TeleportModal from '@/components/gameMaster/zoneEditor/partials/TeleportModal.vue'
import ZoneTiles from '@/components/gameMaster/zoneEditor/ZoneTiles.vue' import ZoneTiles from '@/components/gameMaster/zoneEditor/zonePartials/ZoneTiles.vue'
import ZoneObjects from '@/components/gameMaster/zoneEditor/ZoneObjects.vue' import ZoneObjects from '@/components/gameMaster/zoneEditor/zonePartials/ZoneObjects.vue'
import ZoneEventTiles from '@/components/gameMaster/zoneEditor/ZoneEventTiles.vue' import ZoneEventTiles from '@/components/gameMaster/zoneEditor/zonePartials/ZoneEventTiles.vue'
const gameStore = useGameStore() const gameStore = useGameStore()
const zoneEditorStore = useZoneEditorStore() const zoneEditorStore = useZoneEditorStore()
const tileMap = ref(null as Phaser.Tilemaps.Tilemap | null) const tileMap = ref(null as Phaser.Tilemaps.Tilemap | null)
function clear() {
if (!zoneEditorStore.zone) return
// Clear objects, event tiles and tiles
zoneEditorStore.zone.zoneObjects = []
zoneEditorStore.zone.zoneEventTiles = []
zoneEditorStore.triggerClearTiles()
}
function save() { function save() {
if (!zoneEditorStore.zone) return if (!zoneEditorStore.zone) return

View File

@ -1,31 +1,31 @@
<template> <template>
<Controls :layer="tiles" :depth="0" /> <Controls :layer="tileLayer" :depth="0" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import config from '@/config' import config from '@/config'
import { useScene } from 'phavuer' import { useScene } from 'phavuer'
import { useZoneEditorStore } from '@/stores/zoneEditorStore' import { useZoneEditorStore } from '@/stores/zoneEditorStore'
import { onMounted, onUnmounted } from 'vue' import { onMounted, onUnmounted, watch } from 'vue'
import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/zoneComposable' import { createTileArray, getTile, placeTile, setLayerTiles } from '@/composables/zoneComposable'
import Controls from '@/components/utilities/Controls.vue' import Controls from '@/components/utilities/Controls.vue'
import { useGameStore } from '@/stores/gameStore' import { useGameStore } from '@/stores/gameStore'
import type { AssetDataT } from '@/types' import type { AssetDataT } from '@/types'
const emit = defineEmits(['tilemap:create']) const emit = defineEmits(['tileMap:create'])
const scene = useScene() const scene = useScene()
const gameStore = useGameStore() const gameStore = useGameStore()
const zoneEditorStore = useZoneEditorStore() const zoneEditorStore = useZoneEditorStore()
const zoneTilemap = createTilemap() const tileMap = createTileMap()
const tiles = createTileLayer() const tileLayer = createTileLayer()
/** /**
* A Tilemap is a container for Tilemap data. * A Tilemap is a container for Tilemap data.
* This isn't a display object, rather, it holds data about the map and allows you to add tilesets and tilemap layers to it. * This isn't a display object, rather, it holds data about the map and allows you to add tilesets and tilemap layers to it.
* A map can have one or more tilemap layers, which are the display objects that actually render the tiles. * A map can have one or more tilemap layers, which are the display objects that actually render the tiles.
*/ */
function createTilemap() { function createTileMap() {
const zoneData = new Phaser.Tilemaps.MapData({ const zoneData = new Phaser.Tilemaps.MapData({
width: zoneEditorStore.zone?.width, width: zoneEditorStore.zone?.width,
height: zoneEditorStore.zone?.height, height: zoneEditorStore.zone?.height,
@ -34,9 +34,11 @@ function createTilemap() {
orientation: Phaser.Tilemaps.Orientation.ISOMETRIC, orientation: Phaser.Tilemaps.Orientation.ISOMETRIC,
format: Phaser.Tilemaps.Formats.ARRAY_2D format: Phaser.Tilemaps.Formats.ARRAY_2D
}) })
const tilemap = new Phaser.Tilemaps.Tilemap(scene, zoneData)
emit('tilemap:create', tilemap) const newTileMap = new Phaser.Tilemaps.Tilemap(scene, zoneData)
return tilemap emit('tileMap:create', newTileMap)
return newTileMap
} }
/** /**
@ -46,12 +48,12 @@ function createTileLayer() {
const tilesArray = gameStore.getLoadedAssetsByGroup('tiles') const tilesArray = gameStore.getLoadedAssetsByGroup('tiles')
const tilesetImages = Array.from(tilesArray).map((tile: AssetDataT, index: number) => { const tilesetImages = Array.from(tilesArray).map((tile: AssetDataT, index: number) => {
return zoneTilemap.addTilesetImage(tile.key, tile.key, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y }) return tileMap.addTilesetImage(tile.key, tile.key, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y })
}) as any }) as any
// Add blank tile // Add blank tile
tilesetImages.push(zoneTilemap.addTilesetImage('blank_tile', 'blank_tile', config.tile_size.x, config.tile_size.y, 1, 2, 0, { x: 0, y: -config.tile_size.y })) tilesetImages.push(tileMap.addTilesetImage('blank_tile', 'blank_tile', config.tile_size.x, config.tile_size.y, 1, 2, 0, { x: 0, y: -config.tile_size.y }))
const layer = zoneTilemap.createBlankLayer('tiles', tilesetImages, 0, config.tile_size.y) as Phaser.Tilemaps.TilemapLayer const layer = tileMap.createBlankLayer('tiles', tilesetImages, 0, config.tile_size.y) as Phaser.Tilemaps.TilemapLayer
layer.setDepth(0) layer.setDepth(0)
layer.setCullPadding(2, 2) layer.setCullPadding(2, 2)
@ -79,11 +81,11 @@ function pencil(pointer: Phaser.Input.Pointer) {
if (pointer.event.shiftKey) return if (pointer.event.shiftKey) return
// Check if there is a tile // Check if there is a tile
const tile = getTile(tiles, pointer.worldX, pointer.worldY) const tile = getTile(tileLayer, pointer.worldX, pointer.worldY)
if (!tile) return if (!tile) return
// Place tile // Place tile
placeTile(zoneTilemap, tiles, tile.x, tile.y, zoneEditorStore.selectedTile) placeTile(tileMap, tileLayer, tile.x, tile.y, zoneEditorStore.selectedTile)
// Adjust zoneEditorStore.zone.tiles // Adjust zoneEditorStore.zone.tiles
zoneEditorStore.zone.tiles[tile.y][tile.x] = zoneEditorStore.selectedTile zoneEditorStore.zone.tiles[tile.y][tile.x] = zoneEditorStore.selectedTile
@ -109,11 +111,11 @@ function eraser(pointer: Phaser.Input.Pointer) {
if (pointer.event.altKey) return if (pointer.event.altKey) return
// Check if there is a tile // Check if there is a tile
const tile = getTile(tiles, pointer.worldX, pointer.worldY) const tile = getTile(tileLayer, pointer.worldX, pointer.worldY)
if (!tile) return if (!tile) return
// Place tile // Place tile
placeTile(zoneTilemap, tiles, tile.x, tile.y, 'blank_tile') placeTile(tileMap, tileLayer, tile.x, tile.y, 'blank_tile')
// Adjust zoneEditorStore.zone.tiles // Adjust zoneEditorStore.zone.tiles
zoneEditorStore.zone.tiles[tile.y][tile.x] = 'blank_tile' zoneEditorStore.zone.tiles[tile.y][tile.x] = 'blank_tile'
@ -139,10 +141,10 @@ function paint(pointer: Phaser.Input.Pointer) {
if (pointer.event.altKey) return if (pointer.event.altKey) return
// Set new tileArray with selected tile // Set new tileArray with selected tile
setLayerTiles(zoneTilemap, tiles, createTileArray(zoneTilemap.width, zoneTilemap.height, zoneEditorStore.selectedTile.id)) setLayerTiles(tileMap, tileLayer, createTileArray(tileMap.width, tileMap.height, zoneEditorStore.selectedTile))
// Adjust zoneEditorStore.zone.tiles // Adjust zoneEditorStore.zone.tiles
zoneEditorStore.zone.tiles = createTileArray(zoneTilemap.width, zoneTilemap.height, zoneEditorStore.selectedTile.id) zoneEditorStore.zone.tiles = createTileArray(tileMap.width, tileMap.height, zoneEditorStore.selectedTile)
} }
// When alt is pressed, and the pointer is down, select the tile that the pointer is over // When alt is pressed, and the pointer is down, select the tile that the pointer is over
@ -166,18 +168,30 @@ function tilePicker(pointer: Phaser.Input.Pointer) {
if (!pointer.event.altKey) return if (!pointer.event.altKey) return
// Check if there is a tile // Check if there is a tile
const tile = getTile(tiles, pointer.worldX, pointer.worldY) const tile = getTile(tileLayer, pointer.worldX, pointer.worldY)
if (!tile) return if (!tile) return
// Select the tile // Select the tile
zoneEditorStore.setSelectedTile(zoneEditorStore.zone.tiles[tile.y][tile.x]) zoneEditorStore.setSelectedTile(zoneEditorStore.zone.tiles[tile.y][tile.x])
} }
watch(
() => zoneEditorStore.shouldClearTiles,
(shouldClear) => {
if (shouldClear && zoneEditorStore.zone) {
const blankTiles = createTileArray(tileMap.width, tileMap.height, 'blank_tile')
setLayerTiles(tileMap, tileLayer, blankTiles)
zoneEditorStore.zone.tiles = blankTiles
zoneEditorStore.resetClearTilesFlag()
}
}
)
onMounted(() => { onMounted(() => {
if (!zoneEditorStore.zone?.tiles) { if (!zoneEditorStore.zone?.tiles) {
return return
} }
setLayerTiles(zoneTilemap, tiles, zoneEditorStore.zone.tiles) setLayerTiles(tileMap, tileLayer, zoneEditorStore.zone.tiles)
scene.input.on(Phaser.Input.Events.POINTER_MOVE, pencil) scene.input.on(Phaser.Input.Events.POINTER_MOVE, pencil)
scene.input.on(Phaser.Input.Events.POINTER_MOVE, eraser) scene.input.on(Phaser.Input.Events.POINTER_MOVE, eraser)
@ -191,8 +205,8 @@ onUnmounted(() => {
scene.input.off(Phaser.Input.Events.POINTER_DOWN, paint) scene.input.off(Phaser.Input.Events.POINTER_DOWN, paint)
scene.input.off(Phaser.Input.Events.POINTER_DOWN, tilePicker) scene.input.off(Phaser.Input.Events.POINTER_DOWN, tilePicker)
zoneTilemap.destroyLayer('tiles') tileMap.destroyLayer('tiles')
zoneTilemap.removeAllLayers() tileMap.removeAllLayers()
zoneTilemap.destroy() tileMap.destroy()
}) })
</script> </script>

View File

@ -1,22 +1,25 @@
<template> <template>
<Teleport to="body"> <Teleport to="body">
<div v-if="isModalOpenRef" class="fixed border-solid border-2 border-gray-500 z-50 flex flex-col backdrop-blur-sm shadow-lg" :style="modalStyle"> <div v-if="isModalOpenRef" class="fixed border-solid border-2 border-gray-500 z-50 flex flex-col backdrop-blur-sm shadow-lg" :style="modalStyle">
<!-- Header -->
<div @mousedown="startDrag" class="cursor-move p-2.5 flex justify-between items-center border-solid border-0 border-b border-gray-500 relative"> <div @mousedown="startDrag" class="cursor-move p-2.5 flex justify-between items-center border-solid border-0 border-b border-gray-500 relative">
<div class="rounded-t absolute w-full h-full top-0 left-0 bg-[url('/assets/ui-texture.png')] bg-no-repeat bg-center bg-cover opacity-90"></div> <div class="rounded-t absolute w-full h-full top-0 left-0 bg-[url('/assets/ui-texture.png')] bg-no-repeat bg-center bg-cover opacity-90" />
<div class="relative z-10"> <div class="relative z-10">
<slot name="modalHeader" /> <slot name="modalHeader" />
</div> </div>
<div class="flex gap-2.5"> <div class="flex gap-2.5">
<button @click="toggleFullScreen" class="w-5 h-5 m-0 p-0 relative hover:scale-110 transition-transform duration-300 ease-in-out" v-if="canFullScreen"> <button v-if="canFullScreen" @click="toggleFullScreen" class="w-5 h-5 m-0 p-0 relative hover:scale-110 transition-transform duration-300 ease-in-out">
<img :alt="isFullScreen ? 'exit full-screen' : 'full-screen'" draggable="false" :src="isFullScreen ? '/assets/icons/minimize.svg' : '/assets/icons/increase-size-option.svg'" class="w-3.5 h-3.5 invert" /> <img :alt="isFullScreen ? 'exit full-screen' : 'full-screen'" :src="isFullScreen ? '/assets/icons/minimize.svg' : '/assets/icons/increase-size-option.svg'" class="w-3.5 h-3.5 invert" draggable="false" />
</button> </button>
<button @click="close" v-if="closable" class="w-3.5 h-3.5 m-0 p-0 relative hover:rotate-180 transition-transform duration-300 ease-in-out"> <button v-if="closable" @click="emit('modal:close')" class="w-3.5 h-3.5 m-0 p-0 relative hover:rotate-180 transition-transform duration-300 ease-in-out">
<img alt="close" draggable="false" src="/assets/icons/close-button-white.svg" class="w-full h-full" /> <img alt="close" src="/assets/icons/close-button-white.svg" class="w-full h-full" draggable="false" />
</button> </button>
</div> </div>
</div> </div>
<!-- Body -->
<div class="overflow-hidden grow relative"> <div class="overflow-hidden grow relative">
<div class="rounded-b absolute w-full h-full top-0 left-0 bg-[url('/assets/ui-texture.png')] bg-no-repeat bg-cover bg-center opacity-90"></div> <div class="rounded-b absolute w-full h-full top-0 left-0 bg-[url('/assets/ui-texture.png')] bg-no-repeat bg-cover bg-center opacity-90" />
<div class="relative z-10 h-full"> <div class="relative z-10 h-full">
<slot name="modalBody" /> <slot name="modalBody" />
</div> </div>
@ -27,219 +30,187 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineEmits, onMounted, onUnmounted, ref, watch, computed } from 'vue' import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
const props = defineProps({ interface ModalProps {
isModalOpen: { isModalOpen: boolean
type: Boolean, closable?: boolean
default: false isResizable?: boolean
}, canFullScreen?: boolean
closable: { modalPositionX?: number
type: Boolean, modalPositionY?: number
default: true modalWidth?: number
}, modalHeight?: number
isResizable: { }
type: Boolean,
default: true interface Position {
}, x: number
canFullScreen: { y: number
type: Boolean, width: number
default: false height: number
}, }
modalPositionX: {
type: Number, const props = withDefaults(defineProps<ModalProps>(), {
default: 0 isModalOpen: false,
}, closable: true,
modalPositionY: { isResizable: true,
type: Number, canFullScreen: false,
default: 0 modalPositionX: 0,
}, modalPositionY: 0,
modalWidth: { modalWidth: 500,
type: Number, modalHeight: 280
default: 500
},
modalHeight: {
type: Number,
default: 280
}
}) })
const isModalOpenRef = ref(props.isModalOpen) const emit = defineEmits<{
const emit = defineEmits(['modal:close', 'character:create']) 'modal:close': []
'character:create': []
}>()
const isModalOpenRef = ref(props.isModalOpen)
const width = ref(props.modalWidth) const width = ref(props.modalWidth)
const height = ref(props.modalHeight) const height = ref(props.modalHeight)
const x = ref(0) const x = ref(0)
const y = ref(0) const y = ref(0)
const minWidth = ref(200)
const minHeight = ref(100)
const isResizing = ref(false) const isResizing = ref(false)
const isDragging = ref(false) const isDragging = ref(false)
const isFullScreen = ref(false) const isFullScreen = ref(false)
let startX = 0 const minDimensions = {
let startY = 0 width: 200,
let initialX = 0 height: 100
let initialY = 0 }
let startWidth = 0
let startHeight = 0 let dragState = {
let preFullScreenState = { x: 0, y: 0, width: 0, height: 0 } startX: 0,
startY: 0,
initialX: 0,
initialY: 0,
startWidth: 0,
startHeight: 0
}
let preFullScreenState: Position = { x: 0, y: 0, width: 0, height: 0 }
const modalStyle = computed(() => ({ const modalStyle = computed(() => ({
borderRadius: isFullScreen.value ? '0' : '6px', borderRadius: isFullScreen.value ? '0' : '6px',
top: isFullScreen.value ? '0' : `${y.value}px`, top: isFullScreen.value ? '0' : `${y.value}px`,
left: isFullScreen.value ? '0' : `${x.value}px`, left: isFullScreen.value ? '0' : `${x.value}px`,
width: isFullScreen.value ? '100vw' : `${width.value}px`, width: isFullScreen.value ? '100vw' : `${width.value}px`,
height: isFullScreen.value ? '100vh' : `${height.value}px`, height: isFullScreen.value ? '100vh' : `${height.value}px`
maxWidth: '100vw',
maxHeight: '100vh'
})) }))
function close() {
emit('modal:close')
}
function startResize(event: MouseEvent) { function startResize(event: MouseEvent) {
if (isFullScreen.value) return if (isFullScreen.value) return
isResizing.value = true isResizing.value = true
startWidth = width.value - event.clientX dragState.startWidth = width.value - event.clientX
startHeight = height.value - event.clientY dragState.startHeight = height.value - event.clientY
event.preventDefault() event.preventDefault()
} }
function resizeModal(event: MouseEvent) { function resizeModal(event: MouseEvent) {
if (!isResizing.value || isFullScreen.value) return if (!isResizing.value || isFullScreen.value) return
const newWidth = Math.min(startWidth + event.clientX, window.innerWidth) width.value = Math.max(dragState.startWidth + event.clientX, minDimensions.width)
const newHeight = Math.min(startHeight + event.clientY, window.innerHeight) height.value = Math.max(dragState.startHeight + event.clientY, minDimensions.height)
width.value = Math.max(newWidth, minWidth.value)
height.value = Math.max(newHeight, minHeight.value)
adjustPosition()
}
function stopResize() {
isResizing.value = false
} }
function startDrag(event: MouseEvent) { function startDrag(event: MouseEvent) {
if (isFullScreen.value) return if (isFullScreen.value) return
isDragging.value = true isDragging.value = true
startX = event.clientX dragState = {
startY = event.clientY startX: event.clientX,
initialX = x.value startY: event.clientY,
initialY = y.value initialX: x.value,
initialY: y.value,
startWidth: width.value,
startHeight: height.value
}
event.preventDefault() event.preventDefault()
} }
function drag(event: MouseEvent) { function drag(event: MouseEvent) {
if (!isDragging.value || isFullScreen.value) return if (!isDragging.value || isFullScreen.value) return
const dx = event.clientX - startX x.value = dragState.initialX + (event.clientX - dragState.startX)
const dy = event.clientY - startY y.value = dragState.initialY + (event.clientY - dragState.startY)
x.value = initialX + dx
y.value = initialY + dy
adjustPosition()
}
function stopDrag() {
isDragging.value = false
}
function adjustPosition() {
if (isFullScreen.value) return
x.value = Math.min(x.value, window.innerWidth - width.value)
y.value = Math.min(y.value, window.innerHeight - height.value)
}
function handleResize() {
if (isFullScreen.value) return
width.value = Math.min(width.value, window.innerWidth)
height.value = Math.min(height.value, window.innerHeight)
adjustPosition()
}
function initializePosition() {
width.value = Math.min(props.modalWidth, window.innerWidth)
height.value = Math.min(props.modalHeight, window.innerHeight)
if (props.modalPositionX !== 0 && props.modalPositionY !== 0) {
x.value = props.modalPositionX
y.value = props.modalPositionY
} else {
x.value = (window.innerWidth - width.value) / 2
y.value = (window.innerHeight - height.value) / 2
}
} }
function toggleFullScreen() { function toggleFullScreen() {
if (isFullScreen.value) { if (isFullScreen.value) {
// Exit full-screen Object.assign({ x, y, width, height }, preFullScreenState)
x.value = preFullScreenState.x
y.value = preFullScreenState.y
width.value = preFullScreenState.width
height.value = preFullScreenState.height
isFullScreen.value = false
} else { } else {
// Enter full-screen
preFullScreenState = { x: x.value, y: y.value, width: width.value, height: height.value } preFullScreenState = { x: x.value, y: y.value, width: width.value, height: height.value }
isFullScreen.value = true
} }
isFullScreen.value = !isFullScreen.value
} }
function initializePosition() {
width.value = props.modalWidth
height.value = props.modalHeight
x.value = props.modalPositionX || (window.innerWidth - width.value) / 2
y.value = props.modalPositionY || (window.innerHeight - height.value) / 2
}
// Watchers
watch( watch(
() => props.isModalOpen, () => props.isModalOpen,
(value) => { (value) => {
isModalOpenRef.value = value isModalOpenRef.value = value
if (value) { if (value) initializePosition()
initializePosition()
}
} }
) )
watch( watch(
() => props.modalWidth, () => props.modalWidth,
(value) => { (value) => (width.value = value)
width.value = Math.min(value, window.innerWidth)
}
) )
watch( watch(
() => props.modalHeight, () => props.modalHeight,
(value) => { (value) => (height.value = value)
height.value = Math.min(value, window.innerHeight)
}
) )
watch( watch(
() => props.modalPositionX, () => props.modalPositionX,
(value) => { (value) => (x.value = value)
x.value = value
}
) )
watch( watch(
() => props.modalPositionY, () => props.modalPositionY,
(value) => { (value) => (y.value = value)
y.value = value
}
) )
// Lifecycle hooks
onMounted(() => { onMounted(() => {
addEventListener('mousemove', drag) const handlers: Record<string, EventListener[]> = {
addEventListener('mouseup', stopDrag) mousemove: [(e: Event) => drag(e as MouseEvent), (e: Event) => resizeModal(e as MouseEvent)],
addEventListener('mousemove', resizeModal) mouseup: [
addEventListener('mouseup', stopResize) () => {
if (props.modalPositionX !== 0 && props.modalPositionY !== 0) { isDragging.value = false
addEventListener('resize', handleResize) },
() => {
isResizing.value = false
}
]
} }
Object.entries(handlers).forEach(([event, fns]) => {
fns.forEach((fn) => window.addEventListener(event, fn))
})
initializePosition() initializePosition()
}) })
onUnmounted(() => { onUnmounted(() => {
removeEventListener('mousemove', drag) const handlers: Record<string, EventListener[]> = {
removeEventListener('mouseup', stopDrag) mousemove: [(e: Event) => drag(e as MouseEvent), (e: Event) => resizeModal(e as MouseEvent)],
removeEventListener('mousemove', resizeModal) mouseup: [
removeEventListener('mouseup', stopResize) () => {
if (props.modalPositionX !== 0 && props.modalPositionY !== 0) { isDragging.value = false
removeEventListener('resize', handleResize) },
() => {
isResizing.value = false
}
]
} }
Object.entries(handlers).forEach(([event, fns]) => {
fns.forEach((fn) => window.removeEventListener(event, fn))
})
}) })
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<ZoneTiles :key="zoneStore.zone?.id ?? 0" @tilemap:create="tileMap = $event" /> <ZoneTiles :key="zoneStore.zone?.id ?? 0" @tileMap:create="tileMap = $event" />
<ZoneObjects v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" /> <ZoneObjects v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
<Characters v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" /> <Characters v-if="tileMap" :tilemap="tileMap as Phaser.Tilemaps.Tilemap" />
</template> </template>

View File

@ -1,5 +1,5 @@
<template> <template>
<Controls :layer="tiles" :depth="0" /> <Controls :layer="tileLayer" :depth="0" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -11,19 +11,19 @@ import { FlattenZoneArray, setLayerTiles } from '@/composables/zoneComposable'
import Controls from '@/components/utilities/Controls.vue' import Controls from '@/components/utilities/Controls.vue'
import { unduplicateArray } from '@/utilities' import { unduplicateArray } from '@/utilities'
const emit = defineEmits(['tilemap:create']) const emit = defineEmits(['tileMap:create'])
const scene = useScene() const scene = useScene()
const zoneStore = useZoneStore() const zoneStore = useZoneStore()
const zoneTilemap = createTilemap() const tileMap = createTileMap()
const tiles = createTileLayer() const tileLayer = createTileLayer()
/** /**
* A Tilemap is a container for Tilemap data. * A Tilemap is a container for Tilemap data.
* This isn't a display object, rather, it holds data about the map and allows you to add tilesets and tilemap layers to it. * This isn't a display object, rather, it holds data about the map and allows you to add tilesets and tilemap layers to it.
* A map can have one or more tilemap layers, which are the display objects that actually render the tiles. * A map can have one or more tilemap layers, which are the display objects that actually render the tiles.
*/ */
function createTilemap() { function createTileMap() {
const zoneData = new Phaser.Tilemaps.MapData({ const zoneData = new Phaser.Tilemaps.MapData({
width: zoneStore.zone?.width, width: zoneStore.zone?.width,
height: zoneStore.zone?.height, height: zoneStore.zone?.height,
@ -32,9 +32,11 @@ function createTilemap() {
orientation: Phaser.Tilemaps.Orientation.ISOMETRIC, orientation: Phaser.Tilemaps.Orientation.ISOMETRIC,
format: Phaser.Tilemaps.Formats.ARRAY_2D format: Phaser.Tilemaps.Formats.ARRAY_2D
}) })
const tilemap = new Phaser.Tilemaps.Tilemap(scene, zoneData)
emit('tilemap:create', tilemap) const newTileMap = new Phaser.Tilemaps.Tilemap(scene, zoneData)
return tilemap emit('tileMap:create', newTileMap)
return newTileMap
} }
/** /**
@ -44,12 +46,12 @@ function createTileLayer() {
const tilesArray = unduplicateArray(FlattenZoneArray(zoneStore.zone?.tiles ?? [])) const tilesArray = unduplicateArray(FlattenZoneArray(zoneStore.zone?.tiles ?? []))
const tilesetImages = Array.from(tilesArray).map((tile: any, index: number) => { const tilesetImages = Array.from(tilesArray).map((tile: any, index: number) => {
return zoneTilemap.addTilesetImage(tile, tile, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y }) return tileMap.addTilesetImage(tile, tile, config.tile_size.x, config.tile_size.y, 1, 2, index + 1, { x: 0, y: -config.tile_size.y })
}) as any }) as any
// Add blank tile // Add blank tile
tilesetImages.push(zoneTilemap.addTilesetImage('blank_tile', 'blank_tile', config.tile_size.x, config.tile_size.y, 1, 2, 0, { x: 0, y: -config.tile_size.y })) tilesetImages.push(tileMap.addTilesetImage('blank_tile', 'blank_tile', config.tile_size.x, config.tile_size.y, 1, 2, 0, { x: 0, y: -config.tile_size.y }))
const layer = zoneTilemap.createBlankLayer('tiles', tilesetImages, 0, config.tile_size.y) as Phaser.Tilemaps.TilemapLayer const layer = tileMap.createBlankLayer('tiles', tilesetImages, 0, config.tile_size.y) as Phaser.Tilemaps.TilemapLayer
layer.setDepth(0) layer.setDepth(0)
layer.setCullPadding(2, 2) layer.setCullPadding(2, 2)
@ -57,11 +59,11 @@ function createTileLayer() {
return layer return layer
} }
setLayerTiles(zoneTilemap, tiles, zoneStore.zone?.tiles) setLayerTiles(tileMap, tileLayer, zoneStore.zone?.tiles)
onBeforeUnmount(() => { onBeforeUnmount(() => {
zoneTilemap.destroyLayer('tiles') tileMap.destroyLayer('tiles')
zoneTilemap.removeAllLayers() tileMap.removeAllLayers()
zoneTilemap.destroy() tileMap.destroy()
}) })
</script> </script>

View File

@ -12,7 +12,7 @@ export type TeleportSettings = {
export const useZoneEditorStore = defineStore('zoneEditor', { export const useZoneEditorStore = defineStore('zoneEditor', {
state: () => { state: () => {
return { return {
active: false, active: true,
zone: null as Zone | null, zone: null as Zone | null,
tool: 'move', tool: 'move',
drawMode: 'tile', drawMode: 'tile',
@ -27,6 +27,7 @@ export const useZoneEditorStore = defineStore('zoneEditor', {
isZoneListModalShown: false, isZoneListModalShown: false,
isCreateZoneModalShown: false, isCreateZoneModalShown: false,
isSettingsModalShown: false, isSettingsModalShown: false,
shouldClearTiles: false,
zoneSettings: { zoneSettings: {
name: '', name: '',
width: 0, width: 0,
@ -106,6 +107,13 @@ export const useZoneEditorStore = defineStore('zoneEditor', {
setTeleportSettings(teleportSettings: TeleportSettings) { setTeleportSettings(teleportSettings: TeleportSettings) {
this.teleportSettings = teleportSettings this.teleportSettings = teleportSettings
}, },
triggerClearTiles() {
this.shouldClearTiles = true
},
resetClearTilesFlag() {
this.shouldClearTiles = false
},
reset(resetZone = false) { reset(resetZone = false) {
if (resetZone) this.zone = null if (resetZone) this.zone = null
this.zoneList = [] this.zoneList = []
@ -118,6 +126,7 @@ export const useZoneEditorStore = defineStore('zoneEditor', {
this.isSettingsModalShown = false this.isSettingsModalShown = false
this.isZoneListModalShown = false this.isZoneListModalShown = false
this.isCreateZoneModalShown = false this.isCreateZoneModalShown = false
this.shouldClearTiles = false
} }
} }
}) })