mirror of
https://github.com/trafficlunar/blockmatic.git
synced 2026-06-28 06:34:13 +00:00
refactor: remove image context
This commit is contained in:
parent
aa58b31269
commit
f4ca910d4c
5 changed files with 52 additions and 119 deletions
|
|
@ -5,40 +5,20 @@ import * as PIXI from "pixi.js";
|
|||
import { useApp } from "@pixi/react";
|
||||
import { CompositeTilemap, settings } from "@pixi/tilemap";
|
||||
|
||||
import { findBlockFromRgb } from "@/utils/findBlockFromRgb";
|
||||
|
||||
interface Props {
|
||||
blocks: Block[];
|
||||
setBlocks: React.Dispatch<React.SetStateAction<Block[]>>;
|
||||
missingTexture: PIXI.Texture | undefined;
|
||||
textures: Record<string, PIXI.Texture>;
|
||||
solidTextures: Record<string, PIXI.Texture>;
|
||||
image: HTMLImageElement | undefined;
|
||||
imageDimensions: Dimension;
|
||||
usableBlocks: string[];
|
||||
coords: Position;
|
||||
scale: number;
|
||||
version: number;
|
||||
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
// Lifts 16,000 tiles limit
|
||||
settings.use32bitIndex = true;
|
||||
|
||||
function Blocks({
|
||||
blocks,
|
||||
setBlocks,
|
||||
missingTexture,
|
||||
textures,
|
||||
solidTextures,
|
||||
image,
|
||||
imageDimensions,
|
||||
usableBlocks,
|
||||
coords,
|
||||
scale,
|
||||
version,
|
||||
setLoading,
|
||||
}: Props) {
|
||||
function Blocks({ blocks, missingTexture, textures, solidTextures, coords, scale, version }: Props) {
|
||||
const app = useApp();
|
||||
const tilemapRef = useRef<CompositeTilemap>();
|
||||
|
||||
|
|
@ -80,39 +60,6 @@ function Blocks({
|
|||
tilemapRef.current.scale.set(scale, scale);
|
||||
}, [coords, scale]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!image) return;
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
canvas.width = imageDimensions.width;
|
||||
canvas.height = imageDimensions.height;
|
||||
ctx.drawImage(image, 0, 0, imageDimensions.width, imageDimensions.height);
|
||||
|
||||
const imageData = ctx.getImageData(0, 0, imageDimensions.width, imageDimensions.height);
|
||||
const newBlocks: Block[] = [];
|
||||
|
||||
for (let i = 0; i < imageData.data.length; i += 4) {
|
||||
const block = findBlockFromRgb(usableBlocks, imageData.data[i], imageData.data[i + 1], imageData.data[i + 2], imageData.data[i + 3]);
|
||||
if (block == "air") continue;
|
||||
|
||||
const x = Math.floor((i / 4) % imageData.width);
|
||||
const y = Math.floor(i / 4 / imageData.width);
|
||||
|
||||
newBlocks.push({
|
||||
name: block,
|
||||
x,
|
||||
y,
|
||||
});
|
||||
}
|
||||
|
||||
setBlocks(newBlocks);
|
||||
setLoading(false);
|
||||
}
|
||||
}, [image, imageDimensions]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import * as PIXI from "pixi.js";
|
|||
import { Container, Stage } from "@pixi/react";
|
||||
|
||||
import { CanvasContext } from "@/context/Canvas";
|
||||
import { ImageContext } from "@/context/Image";
|
||||
import { LoadingContext } from "@/context/Loading";
|
||||
import { SettingsContext } from "@/context/Settings";
|
||||
import { TexturesContext } from "@/context/Textures";
|
||||
import { ThemeContext } from "@/context/Theme";
|
||||
|
|
@ -28,8 +26,6 @@ PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
|
|||
|
||||
function Canvas() {
|
||||
const { stageSize, canvasSize, blocks, coords, scale, version, setStageSize, setBlocks, setCoords, setScale } = useContext(CanvasContext);
|
||||
const { image, imageDimensions, usableBlocks } = useContext(ImageContext);
|
||||
const { setLoading } = useContext(LoadingContext);
|
||||
const { settings } = useContext(SettingsContext);
|
||||
const { missingTexture, solidTextures } = useContext(TexturesContext);
|
||||
const { isDark } = useContext(ThemeContext);
|
||||
|
|
@ -320,17 +316,12 @@ function Canvas() {
|
|||
>
|
||||
<Blocks
|
||||
blocks={visibleBlocks}
|
||||
setBlocks={setBlocks}
|
||||
missingTexture={missingTexture}
|
||||
textures={textures}
|
||||
solidTextures={solidTextures}
|
||||
image={image}
|
||||
imageDimensions={imageDimensions}
|
||||
usableBlocks={usableBlocks}
|
||||
coords={coords}
|
||||
scale={scale}
|
||||
version={version}
|
||||
setLoading={setLoading}
|
||||
/>
|
||||
|
||||
<Container x={coords.x} y={coords.y} scale={scale}>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { useDropzone } from "react-dropzone";
|
|||
import { CircleAlertIcon, LinkIcon, UploadIcon } from "lucide-react";
|
||||
|
||||
import { CanvasContext } from "@/context/Canvas";
|
||||
import { ImageContext } from "@/context/Image";
|
||||
import { LoadingContext } from "@/context/Loading";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -22,11 +21,11 @@ import { useBlockData } from "@/hooks/useBlockData";
|
|||
|
||||
import BlockSelector from "./open-image/BlockSelector";
|
||||
import VersionCombobox from "../VersionCombobox";
|
||||
import { findBlockFromRgb } from "@/utils/findBlockFromRgb";
|
||||
|
||||
function OpenImage({ close }: DialogProps) {
|
||||
const { version, setVersion } = useContext(CanvasContext);
|
||||
const { version, setVersion, setBlocks } = useContext(CanvasContext);
|
||||
const { setLoading } = useContext(LoadingContext);
|
||||
const { setImage: setContextImage, setImageDimensions: setContextImageDimensions, setUsableBlocks } = useContext(ImageContext);
|
||||
|
||||
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
||||
accept: {
|
||||
|
|
@ -95,17 +94,44 @@ function OpenImage({ close }: DialogProps) {
|
|||
setSelectedBlocks(newValue);
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
const onSubmit = async () => {
|
||||
if (image) {
|
||||
setLoading(true);
|
||||
setUsableBlocks(selectedBlocks);
|
||||
|
||||
// Wait for loading indicator to appear
|
||||
setTimeout(() => {
|
||||
setContextImage(image);
|
||||
setContextImageDimensions(imageDimensions);
|
||||
close();
|
||||
}, 100);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Load image through JS canvas
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
canvas.width = imageDimensions.width;
|
||||
canvas.height = imageDimensions.height;
|
||||
ctx.drawImage(image, 0, 0, imageDimensions.width, imageDimensions.height);
|
||||
|
||||
const imageData = ctx.getImageData(0, 0, imageDimensions.width, imageDimensions.height);
|
||||
const newBlocks: Block[] = [];
|
||||
|
||||
// Go through each pixel in the image and find block by checking closest RGB to the average color of the texture
|
||||
for (let i = 0; i < imageData.data.length; i += 4) {
|
||||
const block = findBlockFromRgb(selectedBlocks, imageData.data[i], imageData.data[i + 1], imageData.data[i + 2], imageData.data[i + 3]);
|
||||
if (block == "air") continue;
|
||||
|
||||
const x = Math.floor((i / 4) % imageData.width);
|
||||
const y = Math.floor(i / 4 / imageData.width);
|
||||
|
||||
newBlocks.push({
|
||||
name: block,
|
||||
x,
|
||||
y,
|
||||
});
|
||||
}
|
||||
|
||||
setBlocks(newBlocks);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue