feat: rendering for block selector
This commit is contained in:
parent
1acc50012f
commit
e862e5754b
4 changed files with 117 additions and 9 deletions
77
src/components/block-selector/SelectorBlocks.tsx
Normal file
77
src/components/block-selector/SelectorBlocks.tsx
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { useContext, useMemo } from "react";
|
||||||
|
import { Container, Graphics, Sprite, Stage } from "@pixi/react";
|
||||||
|
import * as PIXI from "pixi.js";
|
||||||
|
|
||||||
|
import { BlocksIcon } from "lucide-react";
|
||||||
|
|
||||||
|
import constants from "@/constants";
|
||||||
|
import { TexturesContext } from "@/context/Textures";
|
||||||
|
|
||||||
|
import _blockData from "@/data/blocks/programmer-art/data.json";
|
||||||
|
const blockData: BlockData = _blockData;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
stageWidth: number;
|
||||||
|
searchInput: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectorBlocks({ stageWidth, searchInput }: Props) {
|
||||||
|
const { textures } = useContext(TexturesContext);
|
||||||
|
|
||||||
|
const blocksPerColumn = Math.floor(stageWidth / (32 + 1));
|
||||||
|
const blocks = useMemo(() => Object.keys(blockData).filter((value) => value.includes(searchInput)), [searchInput]);
|
||||||
|
|
||||||
|
const textureCache = useMemo(() => {
|
||||||
|
return (blockName: string) => {
|
||||||
|
let texture = textures[`${blockName}.png`];
|
||||||
|
if (!texture) {
|
||||||
|
const baseTexture = new PIXI.BaseTexture(constants.MISSING_TEXTURE);
|
||||||
|
texture = new PIXI.Texture(baseTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
};
|
||||||
|
}, [textures]);
|
||||||
|
|
||||||
|
const onMouseMove = (e: React.MouseEvent) => {
|
||||||
|
console.log(e.clientX, e.clientY);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (blocks.length == 0) {
|
||||||
|
return (
|
||||||
|
<div className="w-full h-full flex flex-col justify-center items-center gap-1 text-zinc-400">
|
||||||
|
<BlocksIcon size={40} />
|
||||||
|
<span>No blocks found</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stage
|
||||||
|
width={stageWidth}
|
||||||
|
height={Math.ceil(Object.keys(blockData).length / blocksPerColumn) * (32 + 2)}
|
||||||
|
options={{ backgroundAlpha: 0 }}
|
||||||
|
onMouseMove={onMouseMove}
|
||||||
|
>
|
||||||
|
<Container>
|
||||||
|
{blocks.map((block, index) => {
|
||||||
|
const texture = textureCache(block);
|
||||||
|
const x = (index % blocksPerColumn) * (32 + 2);
|
||||||
|
const y = Math.floor(index / blocksPerColumn) * (32 + 2);
|
||||||
|
|
||||||
|
return <Sprite texture={texture} x={x} y={y} scale={2} />;
|
||||||
|
})}
|
||||||
|
|
||||||
|
<Graphics
|
||||||
|
draw={(g) => {
|
||||||
|
g.clear();
|
||||||
|
g.lineStyle(1, 0xffffff, 1);
|
||||||
|
g.drawRect(0, 0, 16, 16);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
</Stage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectorBlocks;
|
||||||
29
src/components/block-selector/index.tsx
Normal file
29
src/components/block-selector/index.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
||||||
|
import SelectorBlocks from "./SelectorBlocks";
|
||||||
|
|
||||||
|
function BlockSelector() {
|
||||||
|
const divRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [stageWidth, setStageWidth] = useState(0);
|
||||||
|
const [searchInput, setSearchInput] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (divRef.current) {
|
||||||
|
setStageWidth(divRef.current.clientWidth);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-72 border-l border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 p-2 pb-0 flex flex-col h-full gap-2">
|
||||||
|
<Input placeholder="Search for blocks..." value={searchInput} onChange={(e) => setSearchInput(e.target.value)} />
|
||||||
|
|
||||||
|
<div ref={divRef} className="w-full flex-1 overflow-y-auto pb-2">
|
||||||
|
<SelectorBlocks stageWidth={stageWidth} searchInput={searchInput} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BlockSelector;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
import * as PIXI from "pixi.js";
|
import * as PIXI from "pixi.js";
|
||||||
import { useApp } from "@pixi/react";
|
import { useApp } from "@pixi/react";
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import { CanvasProvider } from "@/context/Canvas";
|
import { CanvasProvider } from "@/context/Canvas";
|
||||||
import { ImageProvider } from "../context/Image";
|
import { ImageProvider } from "@/context/Image";
|
||||||
import { LoadingProvider } from "@/context/Loading";
|
import { LoadingProvider } from "@/context/Loading";
|
||||||
import { SettingsProvider } from "../context/Settings";
|
import { SettingsProvider } from "@/context/Settings";
|
||||||
import { TexturesProvider } from "../context/Textures";
|
import { TexturesProvider } from "@/context/Textures";
|
||||||
import { ToolProvider } from "../context/Tool";
|
import { ToolProvider } from "@/context/Tool";
|
||||||
|
|
||||||
import Menubar from "../components/menubar";
|
import Menubar from "@/components/menubar";
|
||||||
import Toolbar from "../components/toolbar";
|
import Toolbar from "@/components/toolbar";
|
||||||
import Canvas from "../components/canvas/Canvas";
|
import Canvas from "@/components/canvas/Canvas";
|
||||||
|
import BlockSelector from "@/components/block-selector";
|
||||||
|
|
||||||
function AppPage() {
|
function AppPage() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -17,10 +18,11 @@ function AppPage() {
|
||||||
<SettingsProvider>
|
<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_minmax(0,1fr)] grid-cols-[2.5rem_1fr_auto]">
|
||||||
<Menubar />
|
<Menubar />
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
<Canvas />
|
<Canvas />
|
||||||
|
<BlockSelector />
|
||||||
</main>
|
</main>
|
||||||
</ToolProvider>
|
</ToolProvider>
|
||||||
</TexturesProvider>
|
</TexturesProvider>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue