| @@ -2,8 +2,10 @@ export {JSONMaterialLoader} from './JSONMaterialLoader' | |||
| export {SimpleJSONLoader} from './SimpleJSONLoader' | |||
| export {MTLLoader2, type MaterialCreator} from './MTLLoader2' | |||
| export {OBJLoader2} from './OBJLoader2' | |||
| export {FBXLoader2} from './FBXLoader2' | |||
| export {ZipLoader} from './ZipLoader' | |||
| export {GLTFLoader2, type GLTFPreparser} from './GLTFLoader2' | |||
| export {DRACOLoader2} from './DRACOLoader2' | |||
| export {RGBEPNGLoader} from './RGBEPNGLoader' | |||
| export {Rhino3dmLoader2} from './Rhino3dmLoader2' | |||
| export {SVGTextureLoader} from './SVGTextureLoader' | |||
| @@ -1,5 +1,5 @@ | |||
| import {BufferGeometry, NormalBufferAttributes, NormalOrGLBufferAttributes} from 'three' | |||
| import type {IGeometry, IGeometryEventMap} from '../IGeometry' | |||
| import type {IGeometry, IGeometryEventMap, IGeometryUserData} from '../IGeometry' | |||
| import {iGeometryCommons} from './iGeometryCommons' | |||
| import type {IObject3D} from '../IObject' | |||
| @@ -9,6 +9,7 @@ export class BufferGeometry2<Attributes extends NormalOrGLBufferAttributes = Nor | |||
| setDirty = iGeometryCommons.setDirty | |||
| refreshUi = iGeometryCommons.refreshUi | |||
| appliedMeshes = new Set<IObject3D>() | |||
| declare userData: IGeometryUserData | |||
| constructor() { | |||
| super() | |||
| @@ -2,7 +2,8 @@ import { | |||
| BufferGeometry, | |||
| Color, | |||
| EquirectangularReflectionMapping, | |||
| EventListener, EventListener2, | |||
| EventListener, | |||
| EventListener2, | |||
| IUniform, | |||
| Object3D, | |||
| Scene, | |||
| @@ -44,7 +45,7 @@ export class RootScene<TE extends ISceneEventMap = ISceneEventMap> extends Scene | |||
| @serialize() @onChange2(RootScene.prototype.onBackgroundChange) | |||
| backgroundColor: Color | null = null // read in three.js WebGLBackground | |||
| @onChange2(RootScene.prototype.onBackgroundChange) | |||
| @onChange3(RootScene.prototype.onBackgroundChange) | |||
| @serialize() @uiImage('Background Image') | |||
| background: null | Color | ITexture | 'environment' = null | |||
| /** | |||
| @@ -58,7 +59,7 @@ export class RootScene<TE extends ISceneEventMap = ISceneEventMap> extends Scene | |||
| * The default environment map used when rendering materials in the scene | |||
| */ | |||
| @uiImage('Environment') | |||
| @serialize() @onChange2(RootScene.prototype._onEnvironmentChange) | |||
| @serialize() @onChange3(RootScene.prototype._onEnvironmentChange) | |||
| environment: ITexture | null = null | |||
| /** | |||
| @@ -96,6 +97,12 @@ export class RootScene<TE extends ISceneEventMap = ISceneEventMap> extends Scene | |||
| */ | |||
| @uiConfig() @serialize() readonly defaultCamera: ICamera | |||
| /** | |||
| * Calls dispose on current old environment map, background map when it is changed. | |||
| * Runtime only (not serialized) | |||
| */ | |||
| autoDisposeSceneMaps = true | |||
| // private _environmentLight?: IEnvironmentLight | |||
| // required just because we don't want activeCamera to be null. | |||
| @@ -308,7 +315,11 @@ export class RootScene<TE extends ISceneEventMap = ISceneEventMap> extends Scene | |||
| } | |||
| } | |||
| private _onEnvironmentChange() { | |||
| private _onEnvironmentChange(ev?: {value: ITexture|null, oldValue: ITexture|null}) { | |||
| if (ev?.oldValue && ev.oldValue !== ev.value) { | |||
| if (this.autoDisposeSceneMaps && typeof ev.oldValue.dispose === 'function') ev.oldValue.dispose() | |||
| } | |||
| // console.warn('environment changed') | |||
| if (this.environment?.mapping === UVMapping) { | |||
| this.environment.mapping = EquirectangularReflectionMapping // for PMREMGenerator | |||
| @@ -319,7 +330,11 @@ export class RootScene<TE extends ISceneEventMap = ISceneEventMap> extends Scene | |||
| this.refreshUi?.() | |||
| } | |||
| onBackgroundChange() { | |||
| onBackgroundChange(ev?: {value: ITexture|null, oldValue: ITexture|null}) { | |||
| if (ev?.oldValue && ev.oldValue !== ev.value) { | |||
| if (this.autoDisposeSceneMaps && typeof ev.oldValue.dispose === 'function') ev.oldValue.dispose() | |||
| } | |||
| this.dispatchEvent({type: 'backgroundChanged', background: this.background, backgroundColor: this.backgroundColor}) | |||
| this.setDirty({refreshScene: true, geometryChanged: false}) | |||
| this.refreshUi?.() | |||
| @@ -32,9 +32,7 @@ declare module 'popmotion'{ | |||
| export type {AnimationOptions, KeyframeOptions, Easing} | |||
| function easeInOutSine(x: number): number { | |||
| return -(Math.cos(Math.PI * x) - 1) / 2 | |||
| } | |||
| const easeInOutSine: Easing = (x) => -(Math.cos(Math.PI * x) - 1) / 2 | |||
| // eslint-disable-next-line @typescript-eslint/naming-convention | |||
| export const EasingFunctions = { | |||
| @@ -12,7 +12,7 @@ import { | |||
| Vector3, | |||
| EventListener2, | |||
| } from 'three' | |||
| import {Class, createCanvasElement, downloadBlob, onChange, serialize, ValOrArr} from 'ts-browser-helpers' | |||
| import {Class, createCanvasElement, downloadBlob, onChange, serialize, timeout, ValOrArr} from 'ts-browser-helpers' | |||
| import {TViewerScreenShader} from '../postprocessing' | |||
| import { | |||
| AddObjectOptions, | |||
| @@ -237,7 +237,7 @@ export interface ThreeViewerOptions { | |||
| export class ThreeViewer extends EventDispatcher<Record<IViewerEventTypes, IViewerEvent>> { | |||
| public static readonly VERSION = VERSION | |||
| public static readonly ConfigTypeSlug = 'vjson' | |||
| uiConfig!: UiObjectConfig | |||
| declare uiConfig: UiObjectConfig | |||
| static Console: IConsoleWrapper = { | |||
| log: console.log.bind(console), | |||
| @@ -887,7 +887,9 @@ export class ThreeViewer extends EventDispatcher<Record<IViewerEventTypes, IView | |||
| this._canvas.style.height = size?.height ? size.height + 'px' : '100%' | |||
| // this._canvas.style.maxWidth = '100%' // this is upto the app to do. | |||
| // this._canvas.style.maxHeight = '100%' | |||
| this.resize() | |||
| // https://stackoverflow.com/questions/21664940/force-browser-to-trigger-reflow-while-changing-css | |||
| void this._canvas.offsetHeight | |||
| this.resize() // this is also required in case the browwser doesnt support/fire observer | |||
| } | |||
| // todo make an example for this. | |||
| @@ -990,6 +992,8 @@ export class ThreeViewer extends EventDispatcher<Record<IViewerEventTypes, IView | |||
| this._scene.modelRoot.traverse(callback) | |||
| } | |||
| deleteImportedViewerConfigOnLoad = true | |||
| /** | |||
| * Add an object to the scene model root. | |||
| * If an imported scene model root is passed, it will be loaded with viewer configuration, unless importConfig is false | |||
| @@ -1001,6 +1005,12 @@ export class ThreeViewer extends EventDispatcher<Record<IViewerEventTypes, IView | |||
| const obj = <RootSceneImportResult>imported | |||
| this._scene.loadModelRoot(obj, options) | |||
| if (obj.importedViewerConfig && options?.importConfig !== false) await this.importConfig(obj.importedViewerConfig) | |||
| if (this.deleteImportedViewerConfigOnLoad && obj.importedViewerConfig) { | |||
| timeout(2000).then(()=>{ // todo timeout time? | |||
| delete obj.importedViewerConfig // any useful data in the config should be loaded into userData.__importData by then | |||
| }) | |||
| } | |||
| return this._scene.modelRoot as T | |||
| } | |||
| this._scene.addObject(imported, options) | |||