From 2fd90f5dd4bc6ff597d7087ca6442e5c2b015dfd Mon Sep 17 00:00:00 2001 From: Misode Date: Fri, 3 Jan 2025 05:17:19 +0100 Subject: [PATCH] Add item model preview --- public/images/single_item.png | Bin 0 -> 586 bytes src/app/components/generator/PreviewPanel.tsx | 8 +- .../components/previews/ItemModelPreview.tsx | 77 ++++++++++++++++++ src/app/components/previews/index.ts | 1 + 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 public/images/single_item.png create mode 100644 src/app/components/previews/ItemModelPreview.tsx diff --git a/public/images/single_item.png b/public/images/single_item.png new file mode 100644 index 0000000000000000000000000000000000000000..750a4f96c37fdbdbfc9c4817fbeba39bcb0784d3 GIT binary patch literal 586 zcmeAS@N?(olHy`uVBq!ia0vp^8-O^FgBeJ=7T)m&QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`MFV_7T!Hle|NoC2I~E!mYHn`c-Q5ioN!>hM8c4C11o;I6Wr2V}%A45@ zD8yOd5n0T@z;_UY8Fx&~ehUR|DNig)We7;j%q!9Ja}7~2)icyH`n`vF z8&J)*)CkWsPfsld4j_k>L5h);ff2~^0%B<>8{`8GMrN=$6Oe7l$iyH3q@#d1vz-Mj zo&{usz|As7h8IAO!e}&08Gup~*cn)WDh-T`4Hy?dOaD4VFdw~z$Bq}^-mgFZ(sD0(TsY! z|5(Ur@k6S)Jz>XZY+Y>o%A&t~y|=})pX(kh?z;DU?~euFf3mL6?Efq%qY$yvY|rCA zFN0awIl?%~Kmv+4Tnic!S`)+%GB$}e#gZqnj`#ho$2BbN-z@ImXZi25^})U-_vrgZ n*SgnlyDoa>bFBZBR}znTmv5VA82I2%1ITlpu6{1-oD!M } + if (id === 'item_definition') { + return + } + if (id === 'model') { return } diff --git a/src/app/components/previews/ItemModelPreview.tsx b/src/app/components/previews/ItemModelPreview.tsx new file mode 100644 index 00000000..77ae6711 --- /dev/null +++ b/src/app/components/previews/ItemModelPreview.tsx @@ -0,0 +1,77 @@ +import { ItemRenderer, ItemStack, NbtString } from 'deepslate' +import { Identifier, ItemModel } from 'deepslate/render' +import { useVersion } from '../../contexts/index.js' +import { useAsync } from '../../hooks/useAsync.js' +import { AsyncCancel } from '../../hooks/useAsyncFn.js' +import { getResources, ResourceWrapper } from '../../services/Resources.js' +import { isObject, safeJsonParse } from '../../Utils.js' +import { ErrorPanel } from '../ErrorPanel.jsx' +import type { PreviewProps } from './index.js' + +const PREVIEW_ID = Identifier.parse('misode:preview') +const RENDER_SIZE = 512 + +export const ItemModelPreview = ({ docAndNode, shown }: PreviewProps) => { + const { version } = useVersion() + + const text = docAndNode.doc.getText() + + const { value: render, error } = useAsync(async () => { + if (!shown) return AsyncCancel + const resources = await getResources(version, new Map()) + const data = safeJsonParse(text) ?? {} + if (!isObject(data) || !isObject(data.model)) { + return undefined + } + const itemModel = ItemModel.fromJson(data.model) + const wrapper = new ResourceWrapper(resources, { + getItemModel(id) { + if (id.equals(PREVIEW_ID)) return itemModel + return null + }, + }) + const canvas = document.createElement('canvas') + canvas.width = RENDER_SIZE + canvas.height = RENDER_SIZE + const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true }) + if (!gl) { + throw new Error('Cannot get WebGL2 context') + } + const item = new ItemStack(PREVIEW_ID, 1, new Map(Object.entries({ + 'minecraft:item_model': new NbtString(PREVIEW_ID.toString()), + }))) + const renderer = new ItemRenderer(gl, item, wrapper, { display_context: 'gui' }) + renderer.drawItem() + const url = canvas.toDataURL() + console.log('DRAW', url) + return url + }, [shown, version, text]) + + if (error) { + return + } + + return <> +
+ Container background + {render &&
+ +
} +
+ +} + +const GUI_WIDTH = 176 +const GUI_HEIGHT = 81 +const SLOT_SIZE = 72 + +function slotStyle() { + const x = 52 + const y = 4 + return { + left: `${x*100/GUI_WIDTH}%`, + top: `${y*100/GUI_HEIGHT}%`, + width: `${SLOT_SIZE*100/GUI_WIDTH}%`, + height: `${SLOT_SIZE*100/GUI_HEIGHT}%`, + } +} diff --git a/src/app/components/previews/index.ts b/src/app/components/previews/index.ts index 70e3ada0..3aa6615b 100644 --- a/src/app/components/previews/index.ts +++ b/src/app/components/previews/index.ts @@ -4,6 +4,7 @@ export * from './BiomeSourcePreview.js' export * from './BlockStatePreview.jsx' export * from './DecoratorPreview.js' export * from './DensityFunctionPreview.js' +export * from './ItemModelPreview.jsx' export * from './LootTablePreview.jsx' export * from './ModelPreview.jsx' export * from './NoisePreview.js'