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