Skip to content

Commit

Permalink
Implement ability to change cell color on grid maps
Browse files Browse the repository at this point in the history
Co-authored-by: francisanthony17 <[email protected]>
  • Loading branch information
spaaaacccee and francisanthony17 committed Jan 17, 2024
1 parent a5bd5ba commit 17ca572
Show file tree
Hide file tree
Showing 20 changed files with 284 additions and 70 deletions.
58 changes: 58 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@mui/icons-material": "^5.14.11",
"@mui/lab": "^5.0.0-alpha.146",
"@mui/material": "^5.14.11",
"color-interpolate": "^1.0.5",
"css-element-queries": "^1.2.3",
"downloadjs": "^1.4.7",
"file-select-dialog": "^1.5.4",
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/app-bar/FeaturePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Box, ButtonProps, Typography as Type, useTheme } from "@mui/material";
import { ButtonProps, Typography as Type, useTheme } from "@mui/material";
import { Flex } from "components/generic/Flex";
import { Select } from "components/generic/Select";
import { Space } from "components/generic/Space";
import { find, map, startCase } from "lodash";
import { FeatureDescriptor } from "protocol/FeatureQuery";
import { ReactElement, ReactNode, cloneElement } from "react";
import { AccentColor, getShade } from "theme";
import { FeaturePickerButton } from "./FeaturePickerButton";
import { Flex } from "components/generic/Flex";
import { Space } from "components/generic/Space";

export type Props = {
label?: string;
Expand Down
16 changes: 2 additions & 14 deletions client/src/components/renderer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import { createElement } from "react";
import { mapParsers } from "./map-parser";
import { RendererMap, RendererProps } from "./Renderer";
import { useUIState } from "slices/UIState";

export function JSONRenderer(props: RendererProps) {
const [{ parameters }] = useUIState();
return createElement(renderers[parameters?.format], props);
}

const renderers: RendererMap = {
json: JSONRenderer,
};
import { mapParsers } from "./map-parser";

export function getParser(key = "") {
return mapParsers[key];
}
}
5 changes: 5 additions & 0 deletions client/src/components/renderer/map-parser/Parser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ import { CompiledComponent } from "protocol";
import { ComponentEntry } from "renderer";
import { NodeMatcher } from "../NodeMatcher";
import { Bounds, Point } from "../Size";
import { FC } from "react";
import { EditorSetterProps } from "components/Editor";

export type MapParser = (map?: string, options?: any) => Promise<ParsedMap>;
export type ParsedMapHydrator = (result: ParsedMap) => ParsedMap & MapUtils;
export type MapEditor<Options> = (
map?: string
) => Promise<FC<EditorSetterProps<Options>>>;

export type ParsedMap = {
log: string[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { chain } from "lodash";
import { ParseGridWorkerParameters } from "./parseGrid.worker";

export type GetGridSymbolsReturnType = {
symbols: string[];
};

export type GetGridSymbolsParameters = Pick<ParseGridWorkerParameters, "map">;

export function getGridSymbols({
map: m,
}: GetGridSymbolsParameters): GetGridSymbolsReturnType {
const lines = m.split(/\r?\n/);
const [, , , , ...grid] = lines;
return {
symbols: chain(grid).join("").trim().split("").uniq().value(),
};
}

onmessage = ({ data }: MessageEvent<GetGridSymbolsParameters>) => {
postMessage(getGridSymbols(data));
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { usingWorkerTask } from "workers/usingWorker";
import {
GetGridSymbolsParameters,
GetGridSymbolsReturnType,
} from "./getGridSymbols.worker";
import getGridSymbolsUrl from "./getGridSymbols.worker.ts?worker&url";

export class GetGridSymbolsWorker extends Worker {
constructor() {
super(getGridSymbolsUrl, { type: "module" });
}
}

export const getGridSymbolsAsync = usingWorkerTask<
GetGridSymbolsParameters,
GetGridSymbolsReturnType
>(GetGridSymbolsWorker);
62 changes: 60 additions & 2 deletions client/src/components/renderer/map-parser/grid/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { Typography as Type, useTheme } from "@mui/material";
import { FeaturePicker } from "components/app-bar/FeaturePicker";
import { Option } from "components/layer-editor/Option";
import { entries, set, startCase } from "lodash";
import memo from "memoizee";
import { withProduce } from "produce";
import { byPoint } from "../../NodeMatcher";
import { MapParser, ParsedMapHydrator } from "../Parser";
import { MapEditor, MapParser, ParsedMapHydrator } from "../Parser";
import { getGridSymbolsAsync } from "./getGridSymbolsAsync";
import { Options } from "./parseGrid.worker";
import { parseGridAsync } from "./parseGridAsync";
import interpolate from "color-interpolate";

const { floor } = Math;

Expand All @@ -22,6 +29,57 @@ export const parse: MapParser = memo(
{ normalizer: JSON.stringify }
);

export const editor: MapEditor<{
symbols?: Record<string, string>;
}> = async (map?: string) => {
if (map) {
const { symbols } = await getGridSymbolsAsync({ map });
return withProduce(({ produce, value }) => {
const { palette } = useTheme();
const gradient = interpolate([
palette.background.paper,
palette.text.primary,
]);
const colors = {
auto: "auto",
foreground: gradient(0.85),
gray: gradient(0.425),
transparent: "",
};

return (
<>
{symbols.map((key) => (
<Option
key={key}
label={`Tile color for "${key}"`}
content={
<FeaturePicker
showArrow
label="Color"
value={value?.symbols?.[key] ?? "auto"}
onChange={(v) =>
produce((prev) => {
set(prev, `symbols["${key}"]`, v);
})
}
items={entries(colors).map(([k, v]) => ({
name: startCase(k),
id: v,
value: v,
}))}
/>
}
/>
))}
</>
);
});
} else {
return () => <></>;
}
};

export const hydrate: ParsedMapHydrator = (result) => {
const { width, height } = result.bounds;
return {
Expand All @@ -37,4 +95,4 @@ export const hydrate: ParsedMapHydrator = (result) => {
pointOf: (node) => ({ x: node % width, y: ~~(node / width) }),
matchNode: byPoint,
};
};
};
41 changes: 17 additions & 24 deletions client/src/components/renderer/map-parser/grid/parseGrid.worker.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import {
chain as _,
flatten,
last,
map,
mapValues,
range,
values,
} from "lodash";
import { chain as _, last, map, range } from "lodash";
import { Point, Size } from "protocol";
import { ParsedMap } from "../Parser";
import { getGridSymbols } from "./getGridSymbols.worker";

function map2D<R>(cells: string[], iterator: (t: string) => R) {
return map(cells, (row) => map(row, (cell) => iterator(cell)));
Expand Down Expand Up @@ -94,9 +87,9 @@ export function optimizeGridMap(
}

export type Options = {
colors?: Record<string, string>;
// floor?: string;
// color?: string;
symbols?: Record<string, string>;
floor?: string;
color?: string;
};

export type ParseGridWorkerParameters = {
Expand All @@ -111,21 +104,22 @@ export type ParseGridWorkerReturnType = Pick<

function parseGrid({
map: m,
//map out all symbols within the map to a color
options: { colors } = {
colors: {
".": "black",
"@": "white",
T: "grey",
},
},
options: { symbols: colors = {}, floor = ".", color = "#fff" } = {},
}: ParseGridWorkerParameters): ParseGridWorkerReturnType {
const lines = m.split("\n");
const lines = m.split(/\r?\n/);
const [, h = "", w = "", , ...grid] = lines;
const [width, height] = [w, h].map((d) => +last(d.split(" "))!);

const nodes = _(colors)
.mapValues((color, symbol) => {
const { symbols } = getGridSymbols({ map: m });

const nodes = _(symbols)
.map((symbol) =>
[undefined, "auto"].includes(colors[symbol])
? [symbol, symbol !== floor ? color : ""]
: [symbol, colors[symbol]]
)
.filter(([, color]) => !!color)
.map(([symbol, color]) => {
const nodes = optimizeGridMap(
map2D(grid, (c) => c === symbol),
{ width, height }
Expand All @@ -137,7 +131,6 @@ function parseGrid({
...node,
}));
})
.values()
.flatten()
.value();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ParseGridWorkerParameters, ParseGridWorkerReturnType } from "./parseGrid.worker";
import {
ParseGridWorkerParameters,
ParseGridWorkerReturnType,
} from "./parseGrid.worker";
import { usingMemoizedWorkerTask } from "workers/usingWorker";
import parseGridWorkerUrl from "./parseGrid.worker.ts?worker&url";

Expand All @@ -11,4 +14,4 @@ export class ParseGridWorker extends Worker {
export const parseGridAsync = usingMemoizedWorkerTask<
ParseGridWorkerParameters,
ParseGridWorkerReturnType
>(ParseGridWorker);
>(ParseGridWorker);
Loading

0 comments on commit 17ca572

Please sign in to comment.