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 --- src/renderer/editor/library.tsx | 111 ++++++++++++++++++++++++++-------------- src/renderer/editor/types.ts | 23 ++++----- src/renderer/editor/util.ts | 9 +++- 3 files changed, 90 insertions(+), 53 deletions(-) (limited to 'src') 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); +} -- cgit v1.2.3