summaryrefslogtreecommitdiffstats
path: root/src/renderer/editor/library.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/editor/library.tsx')
-rw-r--r--src/renderer/editor/library.tsx111
1 files changed, 74 insertions, 37 deletions
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 (
+ <div className={classes.tile}>
+ <img className={classes.img} src={src} />
+ <div className={classes.label}>{tiling.meta.name}</div>
+ </div>
+ );
+}
- switch (tiling.size) {
- case 1:
- name = tiling.sprite.name;
- break;
- case 3:
- name = tiling.sprites[1][1].name;
- break;
- }
+async function listTilings(): Promise<string[]> {
+ 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<TilingMeta> {
+ const path = `project/tiling/${id}/meta.json`;
+ const meta = await readJSON(path);
+ return meta as TilingMeta;
+}
- return <img src={image ? `data:image/png;base64,${image}` : undefined} className={classes.tile} />;
+async function loadTilings(): Promise<Tiling[]> {
+ 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 (
<Container>
- <Box display='inline-block'>
- <div className={classes.container}>
+ <Box mb={2}>
+ <div className={classes.grid}>
{tilings.map((tiling, i) => (
<TilingDisplay key={i} tiling={tiling} />
))}
</div>
</Box>
+ <Button variant='contained' color='primary'>
+ Add
+ </Button>
</Container>
);
}