From 0f3df546c2722e933a86f35404548c0f2da8b0a9 Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Fri, 27 Dec 2024 22:15:07 +0000 Subject: [PATCH] feat: exporting to image --- src/components/dialogs/SaveImage.tsx | 84 ++++++++++++++++++++++++++++ src/components/menubar/FileMenu.tsx | 2 +- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/components/dialogs/SaveImage.tsx diff --git a/src/components/dialogs/SaveImage.tsx b/src/components/dialogs/SaveImage.tsx new file mode 100644 index 0000000..b99ee47 --- /dev/null +++ b/src/components/dialogs/SaveImage.tsx @@ -0,0 +1,84 @@ +import { useContext, useState } from "react"; +import * as PIXI from "pixi.js"; + +import { CanvasContext } from "@/context/Canvas"; +import { TexturesContext } from "@/context/Textures"; + +import { Button } from "@/components/ui/button"; +import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; + +function SaveImage({ close }: DialogProps) { + const { blocks, canvasSize } = useContext(CanvasContext); + const { missingTexture, textures } = useContext(TexturesContext); + + const [fileName, setFileName] = useState("blockmatic"); + + const onSubmit = () => { + const width = canvasSize.maxX - canvasSize.minX; + const height = canvasSize.maxY - canvasSize.minY; + + const renderer = new PIXI.Renderer({ + width: 16 * width, + height: 16 * height, + backgroundAlpha: 1, + }); + + const container = new PIXI.Container(); + blocks.forEach((block) => { + const texture = textures[`${block.name}.png`] ?? missingTexture; + const sprite = new PIXI.Sprite(texture); + sprite.x = block.x * 16; + sprite.y = block.y * 16; + container.addChild(sprite); + }); + + const renderTexture = PIXI.RenderTexture.create({ + width: 16 * width, + height: 16 * height, + }); + + renderer.render(container, { renderTexture }); + + const canvas = renderer.extract.canvas(renderTexture); + canvas.toBlob!((blob) => { + if (!blob) return; + + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = "blockmatic.png"; + link.click(); + + URL.revokeObjectURL(link.href); + }); + + renderer.destroy(); + + close(); + }; + + return ( + + + Save as image (.png) + Save your canvas as a full size image + + +
+ setFileName(e.target.value)} /> + .png +
+ + + + + +
+ ); +} + +export default SaveImage; diff --git a/src/components/menubar/FileMenu.tsx b/src/components/menubar/FileMenu.tsx index 1e10587..bbd5921 100644 --- a/src/components/menubar/FileMenu.tsx +++ b/src/components/menubar/FileMenu.tsx @@ -29,7 +29,7 @@ function FileMenu() { .schematic openDialog("SaveLitematic")}>.litematic - image + openDialog("SaveImage")}>image