diff --git a/src/components/canvas/Blocks.tsx b/src/components/canvas/Blocks.tsx index a766f49..257776f 100644 --- a/src/components/canvas/Blocks.tsx +++ b/src/components/canvas/Blocks.tsx @@ -4,12 +4,14 @@ import * as PIXI from "pixi.js"; import { useApp } from "@pixi/react"; import { CompositeTilemap, settings } from "@pixi/tilemap"; -import blocksData from "@/data/blocks/programmer-art/data.json"; +import _blockData from "@/data/blocks/programmer-art/data.json"; +const blockData: BlockData = _blockData; interface Props { blocks: Block[]; setBlocks: React.Dispatch>; textures: Record; + solidTextures: Record; image: HTMLImageElement | undefined; imageDimensions: Dimension; coords: Position; @@ -20,7 +22,7 @@ interface Props { // Lifts 16,000 tiles limit settings.use32bitIndex = true; -function Blocks({ blocks, setBlocks, textures, image, imageDimensions, coords, scale, setLoading }: Props) { +function Blocks({ blocks, setBlocks, textures, solidTextures, image, imageDimensions, coords, scale, setLoading }: Props) { const app = useApp(); const [missingTexture, setMissingTexture] = useState(); @@ -31,9 +33,16 @@ function Blocks({ blocks, setBlocks, textures, image, imageDimensions, coords, s const tilemap = tilemapRef.current; tilemap.clear(); - blocks.forEach((block) => { - tilemap.tile(textures[`${block.name}.png`] ?? missingTexture, block.x * 16, block.y * 16); - }); + // Tile solid colors at smaller scales + if (scale >= 0.5) { + blocks.forEach((block) => { + tilemap.tile(textures[`${block.name}.png`] ?? missingTexture, block.x * 16, block.y * 16); + }); + } else { + blocks.forEach((block) => { + tilemap.tile(solidTextures[`${block.name}`] ?? missingTexture, block.x * 16, block.y * 16); + }); + } }; useEffect(() => { @@ -69,7 +78,7 @@ function Blocks({ blocks, setBlocks, textures, image, imageDimensions, coords, s let closestBlock = ""; let closestDistance = Infinity; - Object.entries(blocksData).forEach(([block, data]) => { + Object.entries(blockData).forEach(([block, data]) => { const distance = Math.sqrt( Math.pow(r - data.color[0], 2) + Math.pow(g - data.color[1], 2) + Math.pow(b - data.color[2], 2) + Math.pow(a - data.color[3], 3) ); diff --git a/src/components/canvas/Canvas.tsx b/src/components/canvas/Canvas.tsx index 04b919c..3c663bd 100644 --- a/src/components/canvas/Canvas.tsx +++ b/src/components/canvas/Canvas.tsx @@ -28,7 +28,7 @@ function Canvas() { const { image, imageDimensions } = useContext(ImageContext); const { setLoading } = useContext(LoadingContext); const { settings } = useContext(SettingsContext); - const textures = useContext(TexturesContext); + const { textures, solidTextures } = useContext(TexturesContext); const { tool, selectedBlock, cssCursor, setTool, setCssCursor } = useContext(ToolContext); const stageContainerRef = useRef(null); @@ -250,6 +250,7 @@ function Canvas() { blocks={visibleBlocks} setBlocks={setBlocks} textures={textures} + solidTextures={solidTextures} image={image} imageDimensions={imageDimensions} coords={coords} diff --git a/src/context/Textures.tsx b/src/context/Textures.tsx index 8a906f3..dd41b73 100644 --- a/src/context/Textures.tsx +++ b/src/context/Textures.tsx @@ -1,27 +1,58 @@ import { createContext, ReactNode, useContext, useEffect, useState } from "react"; -import { BaseTexture, Spritesheet, Texture } from "pixi.js"; +import * as PIXI from "pixi.js"; import { LoadingContext } from "./Loading"; import spritesheet from "@/data/blocks/programmer-art/spritesheet.json"; +import _blockData from "@/data/blocks/programmer-art/data.json"; +const blockData: BlockData = _blockData; interface Props { children: ReactNode; } -export const TexturesContext = createContext({} as Record); +export const TexturesContext = createContext({ + textures: {} as Record, + solidTextures: {} as Record, +}); export const TexturesProvider = ({ children }: Props) => { - const [textures, setTextures] = useState>({}); const { setLoading } = useContext(LoadingContext); + const [textures, setTextures] = useState>({}); + const [solidTextures, setSolidTextures] = useState>({}); + useEffect(() => { - const sheet = new Spritesheet(BaseTexture.from("/blocks/programmer-art/spritesheet.png"), spritesheet); + const sheet = new PIXI.Spritesheet(PIXI.BaseTexture.from("/blocks/programmer-art/spritesheet.png"), spritesheet); sheet.parse().then((t) => { setTextures(t); - setLoading(false); }); + + // Load solid textures + const solidT: Record = {}; + + const canvas = document.createElement("canvas"); + canvas.width = 16; + canvas.height = 16; + + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + Object.entries(blockData).forEach(([blockName, data]) => { + ctx.fillStyle = `rgb(${data.color[0]}, ${data.color[1]}, ${data.color[2]}, ${data.color[3]})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + const image = new Image(); + image.src = canvas.toDataURL(); + + const baseTexture = new PIXI.BaseTexture(image); + const texture = new PIXI.Texture(baseTexture); + solidT[blockName] = texture; + }); + + setSolidTextures(solidT); + setLoading(false); }, []); - return {children}; + return {children}; };