| @@ -9,17 +9,17 @@ | |||
| "browser": "dist/index.js", | |||
| "exports": { | |||
| ".": { | |||
| "import": "./dist/index.mjs", | |||
| "types": "./dist/index.d.ts", | |||
| "require": "./dist/index.js" | |||
| "types": "./dist/index.d.ts", | |||
| "import": "./dist/index.mjs", | |||
| "require": "./dist/index.js" | |||
| }, | |||
| "./dist/": { | |||
| "import": "./dist/", | |||
| "require": "./dist/" | |||
| }, | |||
| "./lib": { | |||
| "import": "./lib/index.js", | |||
| "types": "./lib/index.d.ts" | |||
| "types": "./lib/index.d.ts", | |||
| "import": "./lib/index.js" | |||
| }, | |||
| "./lib/": { | |||
| "import": "./lib/", | |||
| @@ -1,9 +1,9 @@ | |||
| import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer' | |||
| import {absMax, now, onChange, onChange2, PointerDragHelper, serialize} from 'ts-browser-helpers' | |||
| import {uiButton, uiDropdown, uiFolderContainer, uiMonitor, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js' | |||
| import {AnimationAction, AnimationClip, AnimationMixer, LoopOnce, LoopRepeat} from 'three' | |||
| import {AnimationAction, AnimationClip, AnimationMixer, EventListener2, LoopOnce, LoopRepeat, Scene} from 'three' | |||
| import {ProgressivePlugin} from '../pipeline/ProgressivePlugin' | |||
| import {IObject3D} from '../../core' | |||
| import {IObject3D, ISceneEventMap} from '../../core' | |||
| import {generateUUID} from '../../three' | |||
| import type {FrameFadePlugin} from '../pipeline/FrameFadePlugin' | |||
| @@ -474,10 +474,11 @@ export class GLTFAnimationPlugin extends AViewerPluginSync<GLTFAnimationPluginEv | |||
| } | |||
| } | |||
| protected _objectAdded = (ev: any)=>{ | |||
| protected _objectAdded: EventListener2<'addSceneObject', ISceneEventMap, Scene> = (ev)=>{ | |||
| const object = ev.object as IObject3D | |||
| if (!this._viewer) return | |||
| let changed = false | |||
| const isInRoot = ev.options?.addToRoot // for model stage etc | |||
| object.traverse((obj)=>{ | |||
| if (!this._viewer) return | |||
| @@ -491,7 +492,7 @@ export class GLTFAnimationPlugin extends AViewerPluginSync<GLTFAnimationPluginEv | |||
| object.userData.gltfAnim_SyncMaxDuration = true | |||
| } // todo: check why do we need to do this? wont this create problems with looping or is it for that so that looping works in sync. | |||
| const mixer = new AnimationMixer(this._viewer.scene.modelRoot) // add to modelRoot so it works with GLTF export... | |||
| const mixer = new AnimationMixer(isInRoot ? this._viewer.scene : this._viewer.scene.modelRoot) // add to modelRoot so it works with GLTF export... | |||
| const actions = clips.map(an=>mixer.clipAction(an).setLoop(this.loopAnimations ? LoopRepeat : LoopOnce, this.loopRepetitions)) | |||
| actions.forEach(ac=>ac.clampWhenFinished = true) | |||
| @@ -499,7 +500,7 @@ export class GLTFAnimationPlugin extends AViewerPluginSync<GLTFAnimationPluginEv | |||
| this.animations.push({ | |||
| mixer, clips, actions, duration, | |||
| }) | |||
| // todo remove on object dispose | |||
| // todo remove on object dispose/remove | |||
| changed = true | |||
| @@ -20,8 +20,7 @@ export class CanvasSnapshotPlugin extends AViewerPluginSync { | |||
| * @param options waitForProgressive: wait for progressive rendering to finish, default: true | |||
| */ | |||
| async getFile(filename?: string, options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {waitForProgressive: true}): Promise<File|undefined> { | |||
| options.getDataUrl = false | |||
| return await this._getFile(filename || this.filename, options) as File | |||
| return await this._getFile(filename || this.filename, {...options, getDataUrl: false}) as File | |||
| } | |||
| /** | |||
| @@ -29,11 +28,11 @@ export class CanvasSnapshotPlugin extends AViewerPluginSync { | |||
| * @param options waitForProgressive: wait for progressive rendering to finish, default: true | |||
| */ | |||
| async getDataUrl(options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {}): Promise<string> { | |||
| options.getDataUrl = true | |||
| return await this._getFile('', options) as string ?? '' | |||
| return await this._getFile('', {...options, getDataUrl: true}) as string ?? '' | |||
| } | |||
| private async _getFile(filename: string, options: CanvasSnapshotOptions&{waitForProgressive?: boolean} = {}): Promise<File|string|undefined> { | |||
| await this._viewer?.doOnce('postFrame') | |||
| const viewer = this._viewer | |||
| const canvas = this._viewer?.canvas | |||
| if (!viewer || !canvas) return undefined | |||
| @@ -235,3 +235,4 @@ export {GLTFExporter} from 'three/examples/jsm/exporters/GLTFExporter' | |||
| export {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' | |||
| export * from 'three/examples/jsm/utils/BufferGeometryUtils.js' | |||
| export type {Event, EventListener, EventListener2} from 'three' | |||
| export type {MeshPhysicalMaterialParameters, MeshBasicMaterialParameters, MaterialParameters} from 'three' | |||
| @@ -134,7 +134,7 @@ export class ThreeSerialization { | |||
| isType: (obj: any) => obj.isMaterial || obj.metadata?.type === 'Material', | |||
| serialize: (obj: any, meta?: SerializationMetaType) => { | |||
| if (!obj?.isMaterial) throw new Error('Expected a material') | |||
| if (meta?.materials[obj.uuid]) return {uuid: obj.uuid, resource: 'materials'} | |||
| if (meta?.materials?.[obj.uuid]) return {uuid: obj.uuid, resource: 'materials'} | |||
| if (obj.userData.rootPath) { | |||
| // todo | |||
| // it works for textures because image(Source) are immutable | |||
| @@ -163,7 +163,7 @@ export class ThreeSerialization { | |||
| obj.userData = {} | |||
| let res = {} as any | |||
| try { | |||
| res = obj.toJSON(meta, true) // copying userData is handled in toJSON, see MeshStandardMaterial2 | |||
| res = obj.toJSON(meta || meta2, true) // copying userData is handled in toJSON, see MeshStandardMaterial2 | |||
| serializeMaterialUserData(res, userData, meta) | |||
| res.userData.uuid = userData.uuid | |||
| // todo: override generator to mention that this is a custom serializer? | |||