Bladeren bron

Handle material bubbleToObject, implement physical, unlit material fromJSON, some type changes and refactor

master
Palash Bansal 3 jaren geleden
bovenliggende
commit
3605b0448a
No account linked to committer's email address

+ 1
- 1
package.json Bestand weergeven

"build-examples": "tsc --project examples/tsconfig.build.json", "build-examples": "tsc --project examples/tsconfig.build.json",
"dev-examples": "tsc --project examples/tsconfig.build.json -w", "dev-examples": "tsc --project examples/tsconfig.build.json -w",
"serve-docs": "ws -d docs -p 8080", "serve-docs": "ws -d docs -p 8080",
"serve": "ws -d . -p 8000",
"serve": "ws -d . -p 9229",
"docs": "npx typedoc && markdown-to-html", "docs": "npx typedoc && markdown-to-html",
"prepare": "npm run build && npm run build-examples && npm run docs" "prepare": "npm run build && npm run build-examples && npm run docs"
}, },

+ 18
- 0
src/assetmanager/AssetManager.ts Bestand weergeven

this.viewer = viewer this.viewer = viewer
this.viewer.scene.addEventListener('addSceneObject', this._sceneUpdated) this.viewer.scene.addEventListener('addSceneObject', this._sceneUpdated)
this.viewer.scene.addEventListener('materialChanged', this._sceneUpdated) this.viewer.scene.addEventListener('materialChanged', this._sceneUpdated)
this.viewer.scene.addEventListener('beforeDeserialize', this._sceneUpdated)
this._initCacheStorage(simpleCache, storage ?? true) this._initCacheStorage(simpleCache, storage ?? true)


this.importer.addEventListener('processRaw', (event)=>{ this.importer.addEventListener('processRaw', (event)=>{
for (const t of targets) { for (const t of targets) {
this.materials.registerMaterial(t) this.materials.registerMaterial(t)
} }
} else if (event.type === 'beforeDeserialize') {
// object/material/texture to be deserialized
const data = event.data
const meta = event.meta
if (!data.metadata) {
console.warn('Invalid data(no metadata)', data)
}
console.log(data, event)
if (event.material) {
if (data.metadata?.type !== 'Material') {
console.warn('Invalid material data', data)
}
JSONMaterialLoader.DeserializeMaterialJSON(data, this.viewer, meta, event.material).then(()=>{
//
})
}

} else { } else {
console.error('Unexpected') console.error('Unexpected')
} }

+ 8
- 3
src/assetmanager/import/JSONMaterialLoader.ts Bestand weergeven

import {SimpleJSONLoader} from './SimpleJSONLoader' import {SimpleJSONLoader} from './SimpleJSONLoader'
import {ThreeViewer} from '../../viewer' import {ThreeViewer} from '../../viewer'
import {getEmptyMeta, SerializationMetaType, ThreeSerialization} from '../../utils/serialization' import {getEmptyMeta, SerializationMetaType, ThreeSerialization} from '../../utils/serialization'
import {IMaterial} from '../../core'


export class JSONMaterialLoader extends SimpleJSONLoader { export class JSONMaterialLoader extends SimpleJSONLoader {


if (!this.viewer) throw 'Viewer not set in JSONMaterialLoader.' if (!this.viewer) throw 'Viewer not set in JSONMaterialLoader.'


const json = await super.loadAsync(url, onProgress) as any const json = await super.loadAsync(url, onProgress) as any
const meta: SerializationMetaType = getEmptyMeta()
return await JSONMaterialLoader.DeserializeMaterialJSON(json, this.viewer)
}

static async DeserializeMaterialJSON(json: any, viewer: ThreeViewer, meta?: SerializationMetaType, obj?: IMaterial|IMaterial[]) {
meta = meta || getEmptyMeta()
const json2 = {...json} const json2 = {...json}
if (json.images) { if (json.images) {
if (Array.isArray(json.images)) meta.images = Object.fromEntries(json.images.map((i: any) => [i.uuid, i])) if (Array.isArray(json.images)) meta.images = Object.fromEntries(json.images.map((i: any) => [i.uuid, i]))
else meta.materials = json.materials else meta.materials = json.materials
delete json2.materials delete json2.materials
} }
const resources = await this.viewer.loadConfigResources(meta)
return ThreeSerialization.Deserialize(json2, undefined, resources)
const resources = await viewer.loadConfigResources(meta)
return ThreeSerialization.Deserialize(json2, obj || undefined, resources)
} }
} }

+ 3
- 3
src/core/ICamera.ts Bestand weergeven

traverse(callback: (object: IObject3D) => void): void traverse(callback: (object: IObject3D) => void): void
traverseVisible(callback: (object: IObject3D) => void): void traverseVisible(callback: (object: IObject3D) => void): void
traverseAncestors(callback: (object: IObject3D) => void): void traverseAncestors(callback: (object: IObject3D) => void): void
getObjectById(id: number): IObject3D | undefined
getObjectByName(name: string): IObject3D | undefined
getObjectByProperty(name: string, value: string): IObject3D | undefined
getObjectById<T extends IObject3D = IObject3D>(id: number): T | undefined
getObjectByName<T extends IObject3D = IObject3D>(name: string): T | undefined
getObjectByProperty<T extends IObject3D = IObject3D>(name: string, value: string): T | undefined
copy(source: this, recursive?: boolean, distanceFromTarget?: number, ...args: any[]): this copy(source: this, recursive?: boolean, distanceFromTarget?: number, ...args: any[]): this
clone(recursive?: boolean): this clone(recursive?: boolean): this
add(...object: IObject3D[]): this add(...object: IObject3D[]): this

+ 26
- 5
src/core/IMaterial.ts Bestand weergeven

import type {Event, IUniform, Material, MaterialParameters, Shader} from 'three' import type {Event, IUniform, Material, MaterialParameters, Shader} from 'three'
import type {AnyOptions, IDisposable, IJSONSerializable} from 'ts-browser-helpers'
import type {IDisposable, IJSONSerializable} from 'ts-browser-helpers'
import type {MaterialExtension} from '../materials' import type {MaterialExtension} from '../materials'
import type {IUiConfigContainer} from 'uiconfig.js'
import type {SerializationMetaType} from '../utils/serialization'
import type {ChangeEvent, IUiConfigContainer} from 'uiconfig.js'
import type {SerializationMetaType} from '../utils'
import type {IObject3D} from './IObject' import type {IObject3D} from './IObject'
import type {ITexture} from './ITexture' import type {ITexture} from './ITexture'
import type {IImportResultUserData} from '../assetmanager' import type {IImportResultUserData} from '../assetmanager'


export type IMaterialParameters = MaterialParameters & {customMaterialExtensions?: MaterialExtension[]} export type IMaterialParameters = MaterialParameters & {customMaterialExtensions?: MaterialExtension[]}
export type IMaterialEventTypes = 'dispose' | 'materialUpdate' | 'beforeRender' | 'beforeCompile' | 'afterRender' | 'textureChanged'
export type IMaterialEventTypes = 'dispose' | 'materialUpdate' | 'beforeRender' | 'beforeCompile' | 'afterRender' | 'textureChanged' | 'beforeDeserialize'
export type IMaterialEvent<T extends string = IMaterialEventTypes> = Event & { export type IMaterialEvent<T extends string = IMaterialEventTypes> = Event & {
type: T type: T
bubbleToObject?: boolean bubbleToObject?: boolean
bubbleToParent?: boolean
material?: IMaterial material?: IMaterial


texture?: ITexture texture?: ITexture
oldTexture?: ITexture oldTexture?: ITexture

uiChangeEvent?: ChangeEvent
}
export interface IMaterialSetDirtyOptions {
/**
* @default true
*/
bubbleToObject?: boolean,
/**
* @default true
*/
refreshUi?: boolean,
/**
* @default true
*/
needsUpdate?: boolean,
/**
* Event from uiconfig.js
*/
uiChangeEvent?: ChangeEvent,
[key: string]: any
} }
export type IMaterialSetDirtyOptions = AnyOptions & {bubbleToObject?: boolean}
export interface IMaterialUserData extends IImportResultUserData{ export interface IMaterialUserData extends IImportResultUserData{
uuid?: string // adding to userdata also, so that its saved in gltf uuid?: string // adding to userdata also, so that its saved in gltf



+ 5
- 7
src/core/IObject.ts Bestand weergeven

import {IDisposable} from 'ts-browser-helpers' import {IDisposable} from 'ts-browser-helpers'
import {IMaterial, IMaterialEvent} from './IMaterial'
import {IMaterial} from './IMaterial'
import {Event, Object3D} from 'three' import {Event, Object3D} from 'three'
import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js' import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js'
import {IGeometry, IGeometryEvent} from './IGeometry' import {IGeometry, IGeometryEvent} from './IGeometry'
import {GLTF} from 'three/examples/jsm/loaders/GLTFLoader.js' import {GLTF} from 'three/examples/jsm/loaders/GLTFLoader.js'


export type IObject3DEventTypes = 'dispose' | 'materialUpdate' | 'objectUpdate' | 'geometryChanged' | export type IObject3DEventTypes = 'dispose' | 'materialUpdate' | 'objectUpdate' | 'geometryChanged' |
'materialChanged' | 'geometryUpdate' | 'added' | 'removed' | 'select' |
'materialChanged' | 'geometryUpdate' | 'added' | 'removed' | 'select' | 'beforeDeserialize' |
'setView' | 'activateMain' | 'cameraUpdate' // from camera 'setView' | 'activateMain' | 'cameraUpdate' // from camera
// | string // | string
export interface IObject3DEvent<T extends string = IObject3DEventTypes> extends Event { export interface IObject3DEvent<T extends string = IObject3DEventTypes> extends Event {
modelObject: this modelObject: this




// eslint-disable-next-line @typescript-eslint/naming-convention
_onMaterialUpdate?: (e: IMaterialEvent<'materialUpdate'>) => void
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
_onGeometryUpdate?: (e: IGeometryEvent<'geometryUpdate'>) => void _onGeometryUpdate?: (e: IGeometryEvent<'geometryUpdate'>) => void


traverse(callback: (object: IObject3D) => void): void traverse(callback: (object: IObject3D) => void): void
traverseVisible(callback: (object: IObject3D) => void): void traverseVisible(callback: (object: IObject3D) => void): void
traverseAncestors(callback: (object: IObject3D) => void): void traverseAncestors(callback: (object: IObject3D) => void): void
getObjectById(id: number): IObject3D | undefined
getObjectByName(name: string): IObject3D | undefined
getObjectByProperty(name: string, value: string): IObject3D | undefined
getObjectById<T extends IObject3D = IObject3D>(id: number): T | undefined
getObjectByName<T extends IObject3D = IObject3D>(name: string): T | undefined
getObjectByProperty<T extends IObject3D = IObject3D>(name: string, value: string): T | undefined
copy(source: this, recursive?: boolean, ...args: any[]): this copy(source: this, recursive?: boolean, ...args: any[]): this
clone(recursive?: boolean): this clone(recursive?: boolean): this
add(...object: IObject3D[]): this add(...object: IObject3D[]): this

+ 3
- 3
src/core/IScene.ts Bestand weergeven

traverse(callback: (object: IObject3D) => void): void traverse(callback: (object: IObject3D) => void): void
traverseVisible(callback: (object: IObject3D) => void): void traverseVisible(callback: (object: IObject3D) => void): void
traverseAncestors(callback: (object: IObject3D) => void): void traverseAncestors(callback: (object: IObject3D) => void): void
getObjectById(id: number): IObject3D | undefined
getObjectByName(name: string): IObject3D | undefined
getObjectByProperty(name: string, value: string): IObject3D | undefined
getObjectById<T extends IObject3D = IObject3D>(id: number): T | undefined
getObjectByName<T extends IObject3D = IObject3D>(name: string): T | undefined
getObjectByProperty<T extends IObject3D = IObject3D>(name: string, value: string): T | undefined
copy(source: this, recursive?: boolean): this copy(source: this, recursive?: boolean): this
clone(recursive?: boolean): this clone(recursive?: boolean): this
add(...object: IObject3D[]): this add(...object: IObject3D[]): this

+ 3
- 3
src/core/camera/PerspectiveCamera2.ts Bestand weergeven

traverse: (callback: (object: IObject3D) => void) => void traverse: (callback: (object: IObject3D) => void) => void
traverseVisible: (callback: (object: IObject3D) => void) => void traverseVisible: (callback: (object: IObject3D) => void) => void
traverseAncestors: (callback: (object: IObject3D) => void) => void traverseAncestors: (callback: (object: IObject3D) => void) => void
getObjectById: (id: number) => IObject3D | undefined
getObjectByName: (name: string) => IObject3D | undefined
getObjectByProperty: (name: string, value: string) => IObject3D | undefined
getObjectById: <T extends IObject3D = IObject3D>(id: number) => T | undefined
getObjectByName: <T extends IObject3D = IObject3D>(name: string) => T | undefined
getObjectByProperty: <T extends IObject3D = IObject3D>(name: string, value: string) => T | undefined
copy: (source: ICamera|Camera, recursive?: boolean, distanceFromTarget?: number) => this copy: (source: ICamera|Camera, recursive?: boolean, distanceFromTarget?: number) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
add: (...object: IObject3D[]) => this add: (...object: IObject3D[]) => this

+ 19
- 6
src/core/material/IMaterialUi.ts Bestand weergeven

SubtractiveBlending, SubtractiveBlending,
TangentSpaceNormalMap, TangentSpaceNormalMap,
} from 'three' } from 'three'
import {downloadBlob} from 'ts-browser-helpers'
import {downloadBlob, uploadFile} from 'ts-browser-helpers'
import {PhysicalMaterial} from './PhysicalMaterial' import {PhysicalMaterial} from './PhysicalMaterial'
import {getEmptyMeta} from '../../utils/serialization'


export const iMaterialUI = { export const iMaterialUI = {
base: (material: IMaterial): UiObjectConfig[] => [ base: (material: IMaterial): UiObjectConfig[] => [
{ {
type: 'checkbox', type: 'checkbox',
property: [material, 'transparent'], property: [material, 'transparent'],
onChange: material.setDirty,
onChange: (ev)=>material.setDirty({uiChangeEvent: ev}),
}, },
{ {
type: 'dropdown', type: 'dropdown',
{ {
type: 'checkbox', type: 'checkbox',
property: [material, 'depthTest'], property: [material, 'depthTest'],
onChange: material.setDirty,
onChange: (ev)=>material.setDirty({uiChangeEvent: ev}),
}, },
{ {
type: 'checkbox', type: 'checkbox',
property: [material, 'depthWrite'], property: [material, 'depthWrite'],
onChange: material.setDirty,
onChange: (ev)=>material.setDirty({uiChangeEvent: ev}),
}, },
{ {
type: 'slider', type: 'slider',
}, },
{ {
type: 'button', type: 'button',
label: `Download ${material.constructor.TypeSlug}}`,
label: `Download ${material.constructor.TypeSlug}`,
value: ()=>{ value: ()=>{
const blob = new Blob([JSON.stringify(material.toJSON(), null, 2)], {type: 'application/json'}) const blob = new Blob([JSON.stringify(material.toJSON(), null, 2)], {type: 'application/json'})
downloadBlob(blob, `unlit-material.${material.constructor.TypeSlug}`)
downloadBlob(blob, `material.${material.constructor.TypeSlug}`)
},
},
{
type: 'button',
label: `Select ${material.constructor.TypeSlug}`,
value: ()=>{
uploadFile(false, false, material.constructor.TypeSlug).then(async(files)=>files?.[0]?.text()).then((text)=>{
if (!text) return
const json = JSON.parse(text)
if (json.uuid) delete json.uuid // just copy the material properties
material.fromJSON(json, getEmptyMeta())
})
}, },
}, },
()=>material.materialExtensions?.map(v=>v.getUiConfig?.(material, material.uiConfig?.uiRefresh)).filter(v=>v), ()=>material.materialExtensions?.map(v=>v.getUiConfig?.(material, material.uiConfig?.uiRefresh)).filter(v=>v),

+ 8
- 3
src/core/material/PhysicalMaterial.ts Bestand weergeven

readonly appliedMeshes: Set<IObject3D> = new Set() readonly appliedMeshes: Set<IObject3D> = new Set()
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator


label: 'Physical Material', label: 'Physical Material',
uuid: 'MPM2_' + this.uuid, uuid: 'MPM2_' + this.uuid,
expanded: true, expanded: true,
onChange: (ev)=>{
if (!ev.config || ev.config.onChange) return
this.setDirty({uiChangeEvent: ev, needsUpdate: false, refreshUi: true})
},
children: [ children: [
...iMaterialUI.base(this), ...iMaterialUI.base(this),
iMaterialUI.blending(this), iMaterialUI.blending(this),


/** /**
* Deserializes the material from JSON. * Deserializes the material from JSON.
* Textures should be loaded and in meta.textures before calling this method.
* todo - needs to be tested
* Note: some properties that are not serialized in Material.toJSON when they are default values (like side, alphaTest, blending, maps), they wont be reverted back if not present in JSON
* If _internal = true, Textures should be loaded and in meta.textures before calling this method.
* @param data * @param data
* @param meta * @param meta
* @param _internal * @param _internal
ThreeSerialization.Deserialize(data, this, meta, true) ThreeSerialization.Deserialize(data, this, meta, true)
return this.setValues(data) return this.setValues(data)
} }
ThreeSerialization.Deserialize(data, this, meta, false)
this.dispatchEvent({type: 'beforeDeserialize', data, meta, bubbleToObject: true, bubbleToParent: true})
return this return this
} }



+ 2
- 1
src/core/material/UnlitMaterial.ts Bestand weergeven

readonly appliedMeshes: Set<IObject3D> = new Set() readonly appliedMeshes: Set<IObject3D> = new Set()
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator


ThreeSerialization.Deserialize(data, this, meta, true) ThreeSerialization.Deserialize(data, this, meta, true)
return this.setValues(data) return this.setValues(data)
} }
ThreeSerialization.Deserialize(data, this, meta, false)
this.dispatchEvent({type: 'beforeDeserialize', data, meta, bubbleToObject: true, bubbleToParent: true})
return this return this
} }



+ 13
- 2
src/core/material/iMaterialCommons.ts Bestand weergeven

import {copyMaterialUserData} from '../../utils/serialization' import {copyMaterialUserData} from '../../utils/serialization'
import {MaterialExtender, MaterialExtension} from '../../materials' import {MaterialExtender, MaterialExtension} from '../../materials'
import {IScene} from '../IScene' import {IScene} from '../IScene'
import {IMaterial, IMaterialSetDirtyOptions} from '../IMaterial'
import {IMaterial, IMaterialEvent, IMaterialSetDirtyOptions} from '../IMaterial'


/** /**
* Map of all material properties and their default values in three.js - Material.js * Map of all material properties and their default values in three.js - Material.js
threeMaterialPropList, threeMaterialPropList,
setDirty: function(this: IMaterial, options?: IMaterialSetDirtyOptions): void { setDirty: function(this: IMaterial, options?: IMaterialSetDirtyOptions): void {
this.needsUpdate = true this.needsUpdate = true
this.dispatchEvent({bubbleToObject: true, ...options, type: 'materialUpdate', material: this}) // this sets sceneUpdate in root scene
this.dispatchEvent({bubbleToObject: true, bubbleToParent: true, ...options, type: 'materialUpdate'}) // this sets sceneUpdate in root scene
this.uiConfig?.uiRefresh?.(true, 'postFrame', 1) this.uiConfig?.uiRefresh?.(true, 'postFrame', 1)
}, },
setValues: (superSetValues: Material['setValues']): IMaterial['setValues'] => setValues: (superSetValues: Material['setValues']): IMaterial['setValues'] =>


return material return material
}, },
dispatchEvent: (superDispatchEvent: Material['dispatchEvent']): IMaterial['dispatchEvent'] =>
function(this: IMaterial, event: IMaterialEvent): void {
superDispatchEvent.call(this, event)
const type = event.type
if (event.bubbleToObject && (
type === 'beforeDeserialize' || type === 'materialUpdate' // todo - add more events
)) {
this.appliedMeshes.forEach(m => m.dispatchEvent({...event, material: this, type}))
}
},


registerMaterialExtensions: function(this: IMaterial, customMaterialExtensions: MaterialExtension[]): void { registerMaterialExtensions: function(this: IMaterial, customMaterialExtensions: MaterialExtension[]): void {
MaterialExtender.RegisterExtensions(this, customMaterialExtensions) MaterialExtender.RegisterExtensions(this, customMaterialExtensions)
this.assetType = 'material' this.assetType = 'material'
this.setValues = iMaterialCommons.setValues(this.setValues) this.setValues = iMaterialCommons.setValues(this.setValues)
this.clone = iMaterialCommons.clone(this.clone) this.clone = iMaterialCommons.clone(this.clone)
this.dispatchEvent = iMaterialCommons.dispatchEvent(this.dispatchEvent)


// todo: add uiconfig, serialization, other stuff from UnlitMaterial? // todo: add uiconfig, serialization, other stuff from UnlitMaterial?
// dispose uiconfig etc. on dispose // dispose uiconfig etc. on dispose

+ 5
- 5
src/core/object/RootScene.ts Bestand weergeven

} }


/** /**
* Load model root scene exported to GLTF format. Used internally by {@link ThreeViewer.addSceneObject}.
Load model root scene exported to GLTF format. Used internally by {@link ThreeViewer.addSceneObject}.
* @param obj * @param obj
* @param options * @param options
*/ */
traverse: (callback: (object: IObject3D) => void) => void traverse: (callback: (object: IObject3D) => void) => void
traverseVisible: (callback: (object: IObject3D) => void) => void traverseVisible: (callback: (object: IObject3D) => void) => void
traverseAncestors: (callback: (object: IObject3D) => void) => void traverseAncestors: (callback: (object: IObject3D) => void) => void
getObjectById: (id: number) => IObject3D | undefined
getObjectByName: (name: string) => IObject3D | undefined
getObjectByProperty: (name: string, value: string) => IObject3D | undefined
copy: (source: IObject3D, recursive?: boolean) => this
getObjectById: <T extends IObject3D = IObject3D>(id: number) => T | undefined
getObjectByName: <T extends IObject3D = IObject3D>(name: string) => T | undefined
getObjectByProperty: <T extends IObject3D = IObject3D>(name: string, value: string) => T | undefined
copy: (source: this, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ISceneEvent) => void dispatchEvent: (event: ISceneEvent) => void

+ 1
- 9
src/core/object/iObjectCommons.ts Bestand weergeven

import {Event, Mesh, Vector3} from 'three' import {Event, Mesh, Vector3} from 'three'
import {IMaterial, IMaterialEvent} from '../IMaterial'
import {IMaterial} from '../IMaterial'
import {objectHasOwn} from 'ts-browser-helpers' import {objectHasOwn} from 'ts-browser-helpers'
import {IObject3D, IObject3DEvent, IObjectProcessor, IObjectSetDirtyOptions} from '../IObject' import {IObject3D, IObject3DEvent, IObjectProcessor, IObjectSetDirtyOptions} from '../IObject'
import {copyObject3DUserData} from '../../utils/serialization' import {copyObject3DUserData} from '../../utils/serialization'
}) })
} }
}, },
onMaterialUpdate: function(this: IObject3D, e: IMaterialEvent<'materialUpdate'>): void {
if (!e.bubbleToObject) return
this.dispatchEvent({bubbleToParent: true, ...e, object: this, material: e.target})
},
onGeometryUpdate: function(this: IObject3D, e: IGeometryEvent<'geometryUpdate'>): void { onGeometryUpdate: function(this: IObject3D, e: IGeometryEvent<'geometryUpdate'>): void {
if (!e.bubbleToObject) return if (!e.bubbleToObject) return
this.dispatchEvent({bubbleToParent: true, ...e, object: this, geometry: e.geometry}) this.dispatchEvent({bubbleToParent: true, ...e, object: this, geometry: e.geometry})
const mats = Array.isArray(this.material) ? [...(this.material as IMaterial[])] : [this.material!] const mats = Array.isArray(this.material) ? [...(this.material as IMaterial[])] : [this.material!]
for (const mat of mats) { for (const mat of mats) {
if (!mat) continue if (!mat) continue
this._onMaterialUpdate && mat.removeEventListener('materialUpdate', this._onMaterialUpdate)
if (mat.appliedMeshes) { if (mat.appliedMeshes) {
mat.appliedMeshes.delete(this) mat.appliedMeshes.delete(this)
if (mat.userData && mat.appliedMeshes?.size === 0 && mat.userData.disposeOnIdle !== false) if (mat.userData && mat.appliedMeshes?.size === 0 && mat.userData.disposeOnIdle !== false)
} }
materials.push(mat) materials.push(mat)
if (mat) { if (mat) {
this._onMaterialUpdate && mat.addEventListener('materialUpdate', this._onMaterialUpdate)
mat.appliedMeshes.add(this) mat.appliedMeshes.add(this)
} }
} }
if ((this.isMesh || this.isLine) && !this.userData.__meshSetup) { if ((this.isMesh || this.isLine) && !this.userData.__meshSetup) {
this.userData.__meshSetup = true this.userData.__meshSetup = true


this._onMaterialUpdate = (e: IMaterialEvent) => iObjectCommons.eventCallbacks.onMaterialUpdate.call(this, e)
this._onGeometryUpdate = (e: IGeometryEvent) => iObjectCommons.eventCallbacks.onGeometryUpdate.call(this, e) this._onGeometryUpdate = (e: IGeometryEvent) => iObjectCommons.eventCallbacks.onGeometryUpdate.call(this, e)


// Material, Geometry prop init // Material, Geometry prop init
// if (oldGeom && oldGeom.userData && oldGeom.appliedMeshes?.size === 0 && oldGeom.userData.disposeOnIdle !== false) oldGeom.dispose() // if (oldGeom && oldGeom.userData && oldGeom.appliedMeshes?.size === 0 && oldGeom.userData.disposeOnIdle !== false) oldGeom.dispose()
} }


delete this._onMaterialUpdate
delete this._onGeometryUpdate delete this._onGeometryUpdate
}) })



+ 2
- 2
src/utils/serialization.ts Bestand weergeven



// data has deserialized textures and userData, assuming the rest can be deserialized by material.fromJSON // data has deserialized textures and userData, assuming the rest can be deserialized by material.fromJSON


if (!obj || !obj.isMaterial || obj.type !== type) {
if (obj && Object.keys(obj).length) console.warn('Material type mismatch during deserialize, creating a new material', obj, data)
if (!obj || !obj.isMaterial || obj.type !== type && obj.constructor?.TYPE !== type) {
if (obj && Object.keys(obj).length) console.warn('Material type mismatch during deserialize, creating a new material', obj, data, type, obj.constructor?.type)
obj = null obj = null
} }
// if obj is not null // if obj is not null

Laden…
Annuleren
Opslaan