feat: add grid
This commit is contained in:
parent
f2b3910432
commit
30beead56c
6 changed files with 96 additions and 19 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { SettingsProvider } from "./context/SettingsContext";
|
||||||
import { TexturesProvider } from "./context/TexturesContext";
|
import { TexturesProvider } from "./context/TexturesContext";
|
||||||
import { ToolProvider } from "./context/ToolContext";
|
import { ToolProvider } from "./context/ToolContext";
|
||||||
|
|
||||||
|
|
@ -7,6 +8,7 @@ import Canvas from "./components/Canvas";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
|
<SettingsProvider>
|
||||||
<TexturesProvider>
|
<TexturesProvider>
|
||||||
<ToolProvider>
|
<ToolProvider>
|
||||||
<main className="h-screen grid grid-rows-[2.5rem_1fr] grid-cols-[2.5rem_1fr]">
|
<main className="h-screen grid grid-rows-[2.5rem_1fr] grid-cols-[2.5rem_1fr]">
|
||||||
|
|
@ -16,6 +18,7 @@ function App() {
|
||||||
</main>
|
</main>
|
||||||
</ToolProvider>
|
</ToolProvider>
|
||||||
</TexturesProvider>
|
</TexturesProvider>
|
||||||
|
</SettingsProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ import React, { useCallback, useContext, useEffect, useMemo, useRef, useState }
|
||||||
import { Container, Stage } from "@pixi/react";
|
import { Container, Stage } from "@pixi/react";
|
||||||
import * as PIXI from "pixi.js";
|
import * as PIXI from "pixi.js";
|
||||||
|
|
||||||
|
import { SettingsContext } from "@/context/SettingsContext";
|
||||||
import { ToolContext } from "@/context/ToolContext";
|
import { ToolContext } from "@/context/ToolContext";
|
||||||
import { TexturesContext } from "@/context/TexturesContext";
|
import { TexturesContext } from "@/context/TexturesContext";
|
||||||
|
|
||||||
import Blocks from "./Blocks";
|
import Blocks from "./Blocks";
|
||||||
|
import Grid from "./Grid";
|
||||||
import Cursor from "./Cursor";
|
import Cursor from "./Cursor";
|
||||||
import CursorInformation from "./information/Cursor";
|
import CursorInformation from "./information/Cursor";
|
||||||
import CanvasInformation from "./information/Canvas";
|
import CanvasInformation from "./information/Canvas";
|
||||||
|
|
@ -14,11 +16,12 @@ import CanvasInformation from "./information/Canvas";
|
||||||
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
|
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
|
||||||
|
|
||||||
function Canvas() {
|
function Canvas() {
|
||||||
|
const { settings } = useContext(SettingsContext);
|
||||||
const { tool, selectedBlock } = useContext(ToolContext);
|
const { tool, selectedBlock } = useContext(ToolContext);
|
||||||
const textures = useContext(TexturesContext);
|
const textures = useContext(TexturesContext);
|
||||||
|
|
||||||
const stageContainerRef = useRef<HTMLDivElement>(null);
|
const stageContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const [stageSize, setStageSize] = useState({ width: 0, height: 0 });
|
const [stageSize, setStageSize] = useState<Dimension>({ width: 0, height: 0 });
|
||||||
|
|
||||||
const [coords, setCoords] = useState<Position>({ x: 0, y: 0 });
|
const [coords, setCoords] = useState<Position>({ x: 0, y: 0 });
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
|
|
@ -136,6 +139,12 @@ function Canvas() {
|
||||||
<Blocks blocks={blocks} setBlocks={setBlocks} textures={textures} />
|
<Blocks blocks={blocks} setBlocks={setBlocks} textures={textures} />
|
||||||
<Cursor mouseCoords={mouseCoords} />
|
<Cursor mouseCoords={mouseCoords} />
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
{settings.grid && (
|
||||||
|
<Container>
|
||||||
|
<Grid stageSize={stageSize} coords={coords} scale={scale} />
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
</Stage>
|
</Stage>
|
||||||
|
|
||||||
<CursorInformation mouseCoords={mouseCoords} blocks={blocks} />
|
<CursorInformation mouseCoords={mouseCoords} blocks={blocks} />
|
||||||
|
|
|
||||||
32
src/components/Grid.tsx
Normal file
32
src/components/Grid.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Graphics } from "@pixi/react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
stageSize: Dimension;
|
||||||
|
coords: Position;
|
||||||
|
scale: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Grid({ stageSize, coords, scale }: Props) {
|
||||||
|
return (
|
||||||
|
<Graphics
|
||||||
|
draw={(g) => {
|
||||||
|
g.clear();
|
||||||
|
g.lineStyle(1, 0xffffff, 0.1);
|
||||||
|
|
||||||
|
const tileSize = 16 * scale;
|
||||||
|
|
||||||
|
for (let x = coords.x % tileSize; x < stageSize.width; x += tileSize) {
|
||||||
|
g.moveTo(x, 0);
|
||||||
|
g.lineTo(x, stageSize.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let y = coords.y % tileSize; y < stageSize.height; y += tileSize) {
|
||||||
|
g.moveTo(0, y);
|
||||||
|
g.lineTo(stageSize.width, y);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Grid;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { Slider } from "@/components/ui/slider";
|
import { Slider } from "@/components/ui/slider";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -22,8 +22,8 @@ function CanvasInformation({ scale, setScale, blocks }: Props) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: maxX - minX,
|
width: maxX - minX,
|
||||||
y: maxY - minY,
|
height: maxY - minY,
|
||||||
};
|
};
|
||||||
}, [blocks]);
|
}, [blocks]);
|
||||||
|
|
||||||
|
|
@ -36,8 +36,8 @@ function CanvasInformation({ scale, setScale, blocks }: Props) {
|
||||||
<div className="flex flex-col items-end gap-1">
|
<div className="flex flex-col items-end gap-1">
|
||||||
<div className="info-child">{Math.floor(scale * 100)}%</div>
|
<div className="info-child">{Math.floor(scale * 100)}%</div>
|
||||||
<div className="info-child">
|
<div className="info-child">
|
||||||
<span>W: {canvasSize.x} </span>
|
<span>W: {canvasSize.width} </span>
|
||||||
<span>H: {canvasSize.y}</span>
|
<span>H: {canvasSize.height}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
24
src/context/SettingsContext.tsx
Normal file
24
src/context/SettingsContext.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { createContext, ReactNode, useState } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultSettings: Settings = {
|
||||||
|
grid: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SettingsContext = createContext({
|
||||||
|
settings: defaultSettings,
|
||||||
|
setSetting: <K extends keyof Settings>(key: K, value: Settings[K]) => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const SettingsProvider = ({ children }: Props) => {
|
||||||
|
const [settings, setSettings] = useState<Settings>(defaultSettings);
|
||||||
|
|
||||||
|
const setSetting = <K extends keyof Settings>(key: K, value: Settings[K]) => {
|
||||||
|
setSettings((prev) => ({ ...prev, [key]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
return <SettingsContext.Provider value={{ settings, setSetting }}>{children}</SettingsContext.Provider>;
|
||||||
|
};
|
||||||
11
src/types.d.ts
vendored
11
src/types.d.ts
vendored
|
|
@ -2,7 +2,12 @@ type Theme = "dark" | "light" | "system";
|
||||||
|
|
||||||
interface Position {
|
interface Position {
|
||||||
x: number;
|
x: number;
|
||||||
y: number
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Dimension {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Block extends Position {
|
interface Block extends Position {
|
||||||
|
|
@ -10,3 +15,7 @@ interface Block extends Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tool = "hand" | "pencil" | "eraser";
|
type Tool = "hand" | "pencil" | "eraser";
|
||||||
|
|
||||||
|
interface Settings {
|
||||||
|
grid: boolean;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue