@xrengine/server-core
Version:
Shared components for XREngine server
191 lines (173 loc) • 5.45 kB
text/typescript
import {
Extension,
ExtensionProperty,
IProperty,
Nullable,
Property,
PropertyType,
ReaderContext,
TextureInfo,
WriterContext
} from '@gltf-transform/core'
import { prototypeFromId } from '@xrengine/engine/src/renderer/materials/functions/MaterialLibraryFunctions'
import { initializeMaterialLibrary } from '@xrengine/engine/src/renderer/materials/MaterialLibrary'
const EXTENSION_NAME = 'EE_material'
interface IEEMaterialArgs extends IProperty {
[field: string]: any
}
interface IEEMaterial extends IProperty {
uuid: string
name: string
prototype: string
args: EEMaterialArgs
}
interface EEMaterialDef {
uuid?: string
name?: string
prototype?: string
args?: Record<string, any>
}
export class EEMaterialArgs extends Property<IEEMaterialArgs> {
public declare propertyType: 'EEMaterial-Arguments'
protected init(): Nullable<IEEMaterialArgs> {
return {
name: '',
extras: {}
}
}
public getProp(field: string) {
return this.get(field)
}
public getPropRef(field: string) {
return this.getRef(field)
}
public setProp(field: string, value: any) {
this.set(field, value)
}
public setPropRef(field: string, value: any) {
this.setRef(field, value)
}
}
export class EEMaterial extends ExtensionProperty<IEEMaterial> {
public static EXTENSION_NAME = EXTENSION_NAME
public declare extensionName: typeof EXTENSION_NAME
public declare propertyType: 'EEMaterial'
public declare parentTypes: [PropertyType.MATERIAL]
protected init(): void {
this.extensionName = EXTENSION_NAME
this.propertyType = 'EEMaterial'
this.parentTypes = [PropertyType.MATERIAL]
}
protected getDefaults(): Nullable<IEEMaterial> {
return Object.assign(super.getDefaults() as IProperty, {
uuid: '',
name: '',
prototype: '',
args: null
})
}
public get uuid() {
return this.get('uuid')
}
public set uuid(val: string) {
this.set('uuid', val)
}
public get name() {
return this.get('name')
}
public set name(val: string) {
this.set('name', val)
}
public get prototype() {
return this.get('prototype')
}
public set prototype(val: string) {
this.set('prototype', val)
}
public get args() {
return this.getRef('args')
}
public set args(val) {
this.setRef('args', val)
}
}
export class EEMaterialExtension extends Extension {
public readonly extensionName = EXTENSION_NAME
public static readonly EXTENSION_NAME = EXTENSION_NAME
public read(readerContext: ReaderContext): this {
initializeMaterialLibrary()
const materialDefs = readerContext.jsonDoc.json.materials || []
materialDefs.map((def, idx) => {
if (def.extensions?.[EXTENSION_NAME]) {
const eeMaterial = new EEMaterial(this.document.getGraph())
readerContext.materials[idx].setExtension(EXTENSION_NAME, eeMaterial)
const eeDef = def.extensions[EXTENSION_NAME] as EEMaterialDef
if (eeDef.uuid) {
eeMaterial.uuid = eeDef.uuid
}
if (eeDef.name) {
eeMaterial.name = eeDef.name
}
if (eeDef.prototype) {
eeMaterial.prototype = eeDef.prototype
}
if (eeDef.args) {
//eeMaterial.args = eeDef.args
const processedArgs = new EEMaterialArgs(this.document.getGraph())
const defaultArgs = prototypeFromId(eeDef.prototype!).arguments
Object.entries(eeDef.args).map(([field, value]) => {
if (!defaultArgs[field]) {
return //ignore deprecated fields
}
if (defaultArgs[field].type === 'texture') {
processedArgs.setPropRef(field, value ? readerContext.textures[value.index] : null)
} else {
processedArgs.setProp(field, value)
}
})
eeMaterial.args = processedArgs
}
}
})
return this
}
public write(writerContext: WriterContext): this {
const json = writerContext.jsonDoc
this.document
.getRoot()
.listMaterials()
.map((material) => {
const eeMaterial = material.getExtension<EEMaterial>(EXTENSION_NAME)
if (eeMaterial) {
const matIdx = writerContext.materialIndexMap.get(material)!
const matDef = json.json.materials![matIdx]
const extensionDef: EEMaterialDef = {
uuid: eeMaterial.uuid,
name: eeMaterial.name,
prototype: eeMaterial.prototype
}
const matArgs = eeMaterial.args
if (matArgs) {
extensionDef.args = {}
const defaultArgs = prototypeFromId(eeMaterial.prototype).arguments
Object.entries(defaultArgs).map(([field, value]) => {
if (value.type === 'texture') {
const texture = matArgs.getPropRef(field)
if (texture) {
const textureInfo = new TextureInfo(this.document.getGraph())
extensionDef.args![field] = writerContext.createTextureInfoDef(texture, textureInfo)
} else {
extensionDef.args![field] = null
}
} else {
extensionDef.args![field] = matArgs.getProp(field)
}
})
}
matDef.extensions = matDef.extensions || {}
matDef.extensions[EXTENSION_NAME] = extensionDef
}
})
return this
}
}