From 6484d42dabf1482e2ea538d2512537690180b8d2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 22 Mar 2020 01:43:54 +0100 Subject: editor: list tiles in project directory --- package.json | 3 ++ project/tiling/dirt/0_0.png | Bin 0 -> 1035 bytes project/tiling/dirt/meta.json | 5 ++ project/tiling/grass/0_0.png | Bin 0 -> 1296 bytes project/tiling/grass/meta.json | 5 ++ src/renderer/editor/library.tsx | 111 ++++++++++++++++++++++++++------------- src/renderer/editor/types.ts | 23 ++++----- src/renderer/editor/util.ts | 9 +++- yarn.lock | 112 ++++++++++++++++++++++++++++++++++++++-- 9 files changed, 210 insertions(+), 58 deletions(-) create mode 100644 project/tiling/dirt/0_0.png create mode 100644 project/tiling/dirt/meta.json create mode 100644 project/tiling/grass/0_0.png create mode 100644 project/tiling/grass/meta.json diff --git a/package.json b/package.json index b196d25..b8ebd24 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "devDependencies": { "@electron-forge/cli": "^6.0.0-beta.50", "@electron-forge/plugin-webpack": "^6.0.0-beta.50", + "@types/color": "^3.0.1", "@types/electron-devtools-installer": "^2.2.0", "@types/react": "^16.9.23", "@types/react-dom": "^16.9.5", @@ -55,6 +56,8 @@ }, "dependencies": { "@material-ui/core": "^4.9.5", + "color": "^3.1.2", + "fast-glob": "^3.2.2", "gl-matrix": "^3.2.1", "immutable": "^4.0.0-rc.12", "react": "^16.13.0", diff --git a/project/tiling/dirt/0_0.png b/project/tiling/dirt/0_0.png new file mode 100644 index 0000000..5961666 Binary files /dev/null and b/project/tiling/dirt/0_0.png differ diff --git a/project/tiling/dirt/meta.json b/project/tiling/dirt/meta.json new file mode 100644 index 0000000..b31da3e --- /dev/null +++ b/project/tiling/dirt/meta.json @@ -0,0 +1,5 @@ +{ + "name": "Dirt", + "width": 1, + "height": 1 +} diff --git a/project/tiling/grass/0_0.png b/project/tiling/grass/0_0.png new file mode 100644 index 0000000..7835867 Binary files /dev/null and b/project/tiling/grass/0_0.png differ diff --git a/project/tiling/grass/meta.json b/project/tiling/grass/meta.json new file mode 100644 index 0000000..bea3ad8 --- /dev/null +++ b/project/tiling/grass/meta.json @@ -0,0 +1,5 @@ +{ + "name": "Grass", + "width": 1, + "height": 1 +} diff --git a/src/renderer/editor/library.tsx b/src/renderer/editor/library.tsx index 4b7dac7..840bdc9 100644 --- a/src/renderer/editor/library.tsx +++ b/src/renderer/editor/library.tsx @@ -1,46 +1,65 @@ import * as React from 'react'; +const { useCallback, useMemo } = React; import { makeStyles, Theme } from '@material-ui/core/styles'; import Box from '@material-ui/core/Box'; +import Button from '@material-ui/core/Button'; import Container from '@material-ui/core/Container'; -import { Tiling } from './types'; -import { useReadFile } from './util'; +import * as Color from 'color'; +import * as glob from 'fast-glob'; + +import { Tiling, TilingMeta } from './types'; +import { usePromise, useReadFile, readJSON } from './util'; const useStyles = makeStyles((theme: Theme) => ({ - container: { + grid: { display: 'flex', flexWrap: 'wrap', + margin: theme.spacing(-0.5), }, tile: { imageRendering: 'pixelated', - border: `solid 1px ${theme.palette.divider}`, + borderStyle: 'solid', + borderWidth: 1, + borderColor: theme.palette.divider, background: theme.palette.background.paper, + position: 'relative', + width: 130, + height: 130, + margin: theme.spacing(0.5), + // cursor: 'pointer', + // '&:hover': { + // borderColor: theme.palette.text.secondary, + // boxShadow: `0 0 2px 1px ${theme.palette.text.secondary}`, + // }, + }, + img: { + position: 'absolute', + zIndex: 1, width: 128, height: 128, - margin: 4, + }, + label: { + position: 'absolute', + zIndex: 2, + left: 0, + right: 0, + bottom: 0, + height: '37.5%', + padding: theme.spacing(1), + background: Color(theme.palette.background.default) + .fade(0.3) + .string(), }, })); -const tilings: Tiling[] = [ - { - size: 1, - sprite: { name: 'dirt' }, - }, - { - size: 1, - sprite: { name: 'grass' }, - }, - { - size: 1, - sprite: { name: 'road_left' }, - }, - { - size: 1, - sprite: { name: 'road_right' }, - }, -]; +function tilingSprite(tiling: Tiling): string { + const x = (tiling.meta.width - 1) / 2; + const y = (tiling.meta.height - 1) / 2; + return `project/tiling/${tiling.id}/${x}_${y}.png`; +} interface TilingDisplayProps { tiling: Tiling; @@ -49,35 +68,53 @@ interface TilingDisplayProps { function TilingDisplay({ tiling }: TilingDisplayProps): JSX.Element | null { const classes = useStyles(); - let name: string; + const path = tilingSprite(tiling); + const image = useReadFile(path); + const src = useMemo(() => (image ? `data:image/png;base64,${image.toString('base64')}` : undefined), [image]); + return ( +
+ +
{tiling.meta.name}
+
+ ); +} - switch (tiling.size) { - case 1: - name = tiling.sprite.name; - break; - case 3: - name = tiling.sprites[1][1].name; - break; - } +async function listTilings(): Promise { + const matches = await glob('project/tiling/*/meta.json'); + return matches.map((m) => m.split('/')[2]); +} - const path = `static/resources/sprite/tile/${name}.png`; - const image = useReadFile(path, 'base64'); +async function loadTilingMeta(id: string): Promise { + const path = `project/tiling/${id}/meta.json`; + const meta = await readJSON(path); + return meta as TilingMeta; +} - return ; +async function loadTilings(): Promise { + const tilings = await listTilings(); + return Promise.all( + tilings.map((id) => [id, loadTilingMeta(id)] as const).map(async ([id, p]) => ({ id, meta: await p })), + ); } export function Library(): JSX.Element { const classes = useStyles(); + const mkLoadTilings = useCallback(() => loadTilings(), []); + const tilings = usePromise(mkLoadTilings) ?? []; + return ( - -
+ +
{tilings.map((tiling, i) => ( ))}
+ ); } diff --git a/src/renderer/editor/types.ts b/src/renderer/editor/types.ts index 95e1bd2..4235bf4 100644 --- a/src/renderer/editor/types.ts +++ b/src/renderer/editor/types.ts @@ -1,16 +1,11 @@ -export type Tuple3 = [T, T, T]; -export type Grid3x3 = Tuple3>; - -export type Sprite = { +export interface TilingMeta { name: string; -}; + desc?: string; + width: number; + height: number; +} -export type Tiling = - | { - size: 1; - sprite: Sprite; - } - | { - size: 3; - sprites: Grid3x3; - }; +export interface Tiling { + id: string; + meta: TilingMeta; +} diff --git a/src/renderer/editor/util.ts b/src/renderer/editor/util.ts index b2331bb..f816de4 100644 --- a/src/renderer/editor/util.ts +++ b/src/renderer/editor/util.ts @@ -25,7 +25,12 @@ export function usePromise(f: () => Promise): T | null { return value; } -export function useReadFile(path: string, encoding: BufferEncoding): string | null { - const readFile = useCallback(() => fs.promises.readFile(path, encoding), [path, encoding]); +export function useReadFile(path: string): Buffer | null { + const readFile = useCallback(() => fs.promises.readFile(path), [path]); return usePromise(readFile); } + +export async function readJSON(path: string): Promise { + const content = await fs.promises.readFile(path, 'utf8'); + return JSON.parse(content); +} diff --git a/yarn.lock b/yarn.lock index 230b89e..4fddc75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -364,6 +364,27 @@ prop-types "^15.7.2" react-is "^16.8.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -376,11 +397,25 @@ dependencies: defer-to-connect "^1.0.1" -"@types/color-name@^1.1.1": +"@types/color-convert@*": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-1.9.0.tgz#bfa8203e41e7c65471e9841d7e306a7cd8b5172d" + integrity sha512-OKGEfULrvSL2VRbkl/gnjjgbbF7ycIlpSsX7Nkab4MOWi5XxmgBYvuiQ7lcCFY5cPDz7MUNaKgxte2VRmtr4Fg== + dependencies: + "@types/color-name" "*" + +"@types/color-name@*", "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/color@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/color/-/color-3.0.1.tgz#2900490ed04da8116c5058cd5dba3572d5a25071" + integrity sha512-oeUWVaAwI+xINDUx+3F2vJkl/vVB03VChFF/Gl3iQCdbcakjuoJyMOba+3BXRtnBhxZ7uBYqQBi9EpLnvSoztA== + dependencies: + "@types/color-convert" "*" + "@types/electron-devtools-installer@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@types/electron-devtools-installer/-/electron-devtools-installer-2.2.0.tgz#32ee4ebbe99b3daf9847a6d2097dc00b5de94f10" @@ -1390,7 +1425,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -1409,11 +1444,27 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + colors@^1.3.3, colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -2499,6 +2550,18 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +fast-glob@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -2509,6 +2572,13 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastq@^1.6.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.1.tgz#4570c74f2ded173e71cf0beb08ac70bb85826791" + integrity sha512-mpIH5sKYueh3YyeJwqtVo8sORi0CgtmkVbK6kZStpQlZBYQuTzG2CZ7idSiJuA7bY0SFCWUc5WIs+oYumGCQNw== + dependencies: + reusify "^1.0.4" + fd-slicer@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" @@ -2852,7 +2922,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0: +glob-parent@^5.0.0, glob-parent@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== @@ -3328,6 +3398,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -4014,6 +4089,11 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -4038,7 +4118,7 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.0: +micromatch@^4.0.0, micromatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== @@ -4828,6 +4908,11 @@ picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== +picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5446,6 +5531,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -5494,6 +5584,11 @@ run-async@^2.4.0: dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -5693,6 +5788,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + single-line-log@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" -- cgit v1.2.3