diff --git a/public/images/single_item.png b/public/images/single_item.png
new file mode 100644
index 00000000..750a4f96
Binary files /dev/null and b/public/images/single_item.png differ
diff --git a/src/app/components/generator/PreviewPanel.tsx b/src/app/components/generator/PreviewPanel.tsx
index df9142db..fe30da09 100644
--- a/src/app/components/generator/PreviewPanel.tsx
+++ b/src/app/components/generator/PreviewPanel.tsx
@@ -5,9 +5,9 @@ import { useVersion } from '../../contexts/Version.jsx'
import { checkVersion } from '../../services/index.js'
import { safeJsonParse } from '../../Utils.js'
import { ErrorPanel } from '../ErrorPanel.jsx'
-import { BiomeSourcePreview, BlockStatePreview, DecoratorPreview, DensityFunctionPreview, LootTablePreview, ModelPreview, NoisePreview, NoiseSettingsPreview, RecipePreview, StructureSetPreview } from '../previews/index.js'
+import { BiomeSourcePreview, BlockStatePreview, DecoratorPreview, DensityFunctionPreview, ItemModelPreview, LootTablePreview, ModelPreview, NoisePreview, NoiseSettingsPreview, RecipePreview, StructureSetPreview } from '../previews/index.js'
-export const HasPreview = ['loot_table', 'recipe', 'dimension', 'worldgen/density_function', 'worldgen/noise', 'worldgen/noise_settings', 'worldgen/configured_feature', 'worldgen/placed_feature', 'worldgen/structure_set', 'block_definition', 'model']
+export const HasPreview = ['loot_table', 'recipe', 'dimension', 'worldgen/density_function', 'worldgen/noise', 'worldgen/noise_settings', 'worldgen/configured_feature', 'worldgen/placed_feature', 'worldgen/structure_set', 'block_definition', 'item_definition', 'model']
type PreviewPanelProps = {
id: string,
@@ -78,6 +78,10 @@ export function PreviewContent({ id, docAndNode, shown }: PreviewContentProps) {
return
}
+ 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 <>
+
+

+ {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'