import React, { useCallback, useEffect } from 'react' import { Material, Texture } from 'three' import styles from '@xrengine/editor/src/components/layout/styles.module.scss' import { AssetLoader } from '@xrengine/engine/src/assets/classes/AssetLoader' import createReadableTexture from '@xrengine/engine/src/assets/functions/createReadableTexture' import { changeMaterialPrototype, materialFromId, prototypeFromId } from '@xrengine/engine/src/renderer/materials/functions/MaterialLibraryFunctions' import { useMaterialLibrary } from '@xrengine/engine/src/renderer/materials/MaterialLibrary' import { useState } from '@xrengine/hyperflux' import { Box, Divider, Stack } from '@mui/material' import { EditorControlFunctions } from '../../functions/EditorControlFunctions' import { accessSelectionState } from '../../services/SelectionServices' import { InputGroup } from '../inputs/InputGroup' import ParameterInput from '../inputs/ParameterInput' import SelectInput from '../inputs/SelectInput' import StringInput from '../inputs/StringInput' export default function MaterialEditor({ material, ...rest }: { ['material']: Material }) { if (material === undefined) return <> const materialComponent = useState(materialFromId(material.uuid)) const prototypeComponent = useState(prototypeFromId(materialComponent.prototype.value)) const loadingData = useState(false) const selectionState = accessSelectionState() const materialLibrary = useMaterialLibrary() const prototypes = Object.values(materialLibrary.prototypes.value).map((prototype) => ({ label: prototype.prototypeId, value: prototype.prototypeId })) const thumbnails = useState>({}) const createThumbnails = useCallback(async () => { const result = {} as Record await Promise.allSettled( Object.entries(material).map(([k, field]: [string, Texture]) => { if (field?.isTexture) { try { return createReadableTexture(field, { maxDimensions: { width: 256, height: 256 }, url: true }).then( (src) => { result[k] = src as string } ) } catch (e) { console.warn('failed loading thumbnail: ' + e) } } }) ) return result }, [materialComponent.parameters, materialComponent.material.uuid, materialComponent.prototype]) const clearThumbs = async () => { thumbnails.promised && (await thumbnails.promise) Object.values(thumbnails.value).map(URL.revokeObjectURL) thumbnails.set({}) } useEffect(() => { loadingData.set(true) clearThumbs() .then(createThumbnails) .then((nuThumbs) => { thumbnails.set(nuThumbs) loadingData.set(false) }) }, [materialComponent.prototype, materialComponent.material]) return (
{materialComponent.src.type.value}
{materialComponent.src.value.path}

{!loadingData.get() && ( { const nuMat = changeMaterialPrototype(material, protoId) materialComponent.set(materialFromId(nuMat!.uuid)) prototypeComponent.set(prototypeFromId(materialComponent.prototype.value)) }} /> )}
async (val) => { let prop if (prototypeComponent.arguments.value[k].type === 'texture' && typeof val === 'string') { if (val) { prop = await AssetLoader.loadAsync(val) } else { prop = undefined } } else { prop = val } EditorControlFunctions.modifyMaterial( selectionState.value.selectedEntities.filter((val) => typeof val === 'string') as string[], material.uuid, [{ [k]: prop }] ) materialComponent.parameters[k].set(prop) }} defaults={loadingData.get() ? {} : prototypeComponent.arguments.value} thumbnails={thumbnails.value} /> {/* */}
) }