From 1605e743f44b835e99b3403cb3cfc5018b697d26 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 19 Mar 2020 23:12:13 +0100 Subject: editor: experiment with Material UI for sprite library implementation --- src/renderer/editor/editor.tsx | 62 ++++++++++++++++++++++++++++-- src/renderer/editor/library.tsx | 83 +++++++++++++++++++++++++++++++++++++++++ src/renderer/editor/types.ts | 16 ++++++++ src/renderer/editor/util.ts | 31 +++++++++++++++ 4 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 src/renderer/editor/library.tsx create mode 100644 src/renderer/editor/types.ts create mode 100644 src/renderer/editor/util.ts (limited to 'src/renderer/editor') diff --git a/src/renderer/editor/editor.tsx b/src/renderer/editor/editor.tsx index fd8360a..2c57afc 100644 --- a/src/renderer/editor/editor.tsx +++ b/src/renderer/editor/editor.tsx @@ -1,10 +1,64 @@ import * as React from 'react'; -import Button from '@material-ui/core/Button'; + +import 'typeface-roboto'; + +import { createMuiTheme, makeStyles, Theme, ThemeProvider } from '@material-ui/core/styles'; + +import CssBaseline from '@material-ui/core/CssBaseline'; +import Drawer from '@material-ui/core/Drawer'; + +import { Library } from './library'; + +const drawerWidth = 240; + +const useStyles = makeStyles((theme: Theme) => ({ + root: { + display: 'flex', + }, + drawer: { + width: drawerWidth, + flexShrink: 0, + }, + drawerPaper: { + width: drawerWidth, + }, + content: { + flexGrow: 1, + padding: theme.spacing(3), + }, +})); + +function EditorLayout(): JSX.Element { + const classes = useStyles(); + + return ( +
+ + +
+ +
+
+ ); +} + +const theme = createMuiTheme({ + palette: { + type: 'dark', + }, +}); export function Editor(): JSX.Element { return ( - + + + ); } diff --git a/src/renderer/editor/library.tsx b/src/renderer/editor/library.tsx new file mode 100644 index 0000000..4b7dac7 --- /dev/null +++ b/src/renderer/editor/library.tsx @@ -0,0 +1,83 @@ +import * as React from 'react'; + +import { makeStyles, Theme } from '@material-ui/core/styles'; + +import Box from '@material-ui/core/Box'; +import Container from '@material-ui/core/Container'; + +import { Tiling } from './types'; +import { useReadFile } from './util'; + +const useStyles = makeStyles((theme: Theme) => ({ + container: { + display: 'flex', + flexWrap: 'wrap', + }, + tile: { + imageRendering: 'pixelated', + border: `solid 1px ${theme.palette.divider}`, + background: theme.palette.background.paper, + width: 128, + height: 128, + margin: 4, + }, +})); + +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' }, + }, +]; + +interface TilingDisplayProps { + tiling: Tiling; +} + +function TilingDisplay({ tiling }: TilingDisplayProps): JSX.Element | null { + const classes = useStyles(); + + let name: string; + + switch (tiling.size) { + case 1: + name = tiling.sprite.name; + break; + case 3: + name = tiling.sprites[1][1].name; + break; + } + + const path = `static/resources/sprite/tile/${name}.png`; + const image = useReadFile(path, 'base64'); + + return ; +} + +export function Library(): JSX.Element { + const classes = useStyles(); + + return ( + + +
+ {tilings.map((tiling, i) => ( + + ))} +
+
+
+ ); +} diff --git a/src/renderer/editor/types.ts b/src/renderer/editor/types.ts new file mode 100644 index 0000000..95e1bd2 --- /dev/null +++ b/src/renderer/editor/types.ts @@ -0,0 +1,16 @@ +export type Tuple3 = [T, T, T]; +export type Grid3x3 = Tuple3>; + +export type Sprite = { + name: string; +}; + +export type Tiling = + | { + size: 1; + sprite: Sprite; + } + | { + size: 3; + sprites: Grid3x3; + }; diff --git a/src/renderer/editor/util.ts b/src/renderer/editor/util.ts new file mode 100644 index 0000000..b2331bb --- /dev/null +++ b/src/renderer/editor/util.ts @@ -0,0 +1,31 @@ +import { useCallback, useEffect, useState } from 'react'; + +import * as fs from 'fs'; + +export function usePromise(f: () => Promise): T | null { + const [value, setValue] = useState(null); + + useEffect(() => { + setValue(null); + + let cancelled = false; + + (async (): Promise => { + const v = await f(); + if (!cancelled) { + setValue(v); + } + })(); + + return (): void => { + cancelled = true; + }; + }, [f]); + + return value; +} + +export function useReadFile(path: string, encoding: BufferEncoding): string | null { + const readFile = useCallback(() => fs.promises.readFile(path, encoding), [path, encoding]); + return usePromise(readFile); +} -- cgit v1.2.3