mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-23 07:10:41 +00:00
Add item model preview
This commit is contained in:
BIN
public/images/single_item.png
Normal file
BIN
public/images/single_item.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 586 B |
@@ -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 <BlockStatePreview {...{ docAndNode, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'item_definition') {
|
||||
return <ItemModelPreview {...{ docAndNode, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'model') {
|
||||
return <ModelPreview {...{ docAndNode, shown }} />
|
||||
}
|
||||
|
||||
77
src/app/components/previews/ItemModelPreview.tsx
Normal file
77
src/app/components/previews/ItemModelPreview.tsx
Normal file
@@ -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 <ErrorPanel error={error} prefix="Failed to initialize preview: " />
|
||||
}
|
||||
|
||||
return <>
|
||||
<div class="preview-overlay">
|
||||
<img src="/images/single_item.png" alt="Container background" class="pixelated" draggable={false} />
|
||||
{render && <div class="flex items-center justify-center" style={slotStyle()}>
|
||||
<img src={render} class="w-[88.888%]" />
|
||||
</div>}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
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}%`,
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user