| export {SimpleJSONLoader} from './SimpleJSONLoader' | export {SimpleJSONLoader} from './SimpleJSONLoader' | ||||
| export {MTLLoader2, type MaterialCreator} from './MTLLoader2' | export {MTLLoader2, type MaterialCreator} from './MTLLoader2' | ||||
| export {OBJLoader2} from './OBJLoader2' | export {OBJLoader2} from './OBJLoader2' | ||||
| export {FBXLoader2} from './FBXLoader2' | |||||
| export {ZipLoader} from './ZipLoader' | export {ZipLoader} from './ZipLoader' | ||||
| export {GLTFLoader2, type GLTFPreparser} from './GLTFLoader2' | export {GLTFLoader2, type GLTFPreparser} from './GLTFLoader2' | ||||
| export {DRACOLoader2} from './DRACOLoader2' | export {DRACOLoader2} from './DRACOLoader2' | ||||
| export {RGBEPNGLoader} from './RGBEPNGLoader' | export {RGBEPNGLoader} from './RGBEPNGLoader' | ||||
| export {Rhino3dmLoader2} from './Rhino3dmLoader2' | export {Rhino3dmLoader2} from './Rhino3dmLoader2' | ||||
| export {SVGTextureLoader} from './SVGTextureLoader' |
| import {BufferGeometry, NormalBufferAttributes, NormalOrGLBufferAttributes} from 'three' | import {BufferGeometry, NormalBufferAttributes, NormalOrGLBufferAttributes} from 'three' | ||||
| import type {IGeometry, IGeometryEventMap} from '../IGeometry' | |||||
| import type {IGeometry, IGeometryEventMap, IGeometryUserData} from '../IGeometry' | |||||
| import {iGeometryCommons} from './iGeometryCommons' | import {iGeometryCommons} from './iGeometryCommons' | ||||
| import type {IObject3D} from '../IObject' | import type {IObject3D} from '../IObject' | ||||
| setDirty = iGeometryCommons.setDirty | setDirty = iGeometryCommons.setDirty | ||||
| refreshUi = iGeometryCommons.refreshUi | refreshUi = iGeometryCommons.refreshUi | ||||
| appliedMeshes = new Set<IObject3D>() | appliedMeshes = new Set<IObject3D>() | ||||
| declare userData: IGeometryUserData | |||||
| constructor() { | constructor() { | ||||
| super() | super() |
| BufferGeometry, | BufferGeometry, | ||||
| Color, | Color, | ||||
| EquirectangularReflectionMapping, | EquirectangularReflectionMapping, | ||||
| EventListener, EventListener2, | |||||
| EventListener, | |||||
| EventListener2, | |||||
| IUniform, | IUniform, | ||||
| Object3D, | Object3D, | ||||
| Scene, | Scene, | ||||
| @serialize() @onChange2(RootScene.prototype.onBackgroundChange) | @serialize() @onChange2(RootScene.prototype.onBackgroundChange) | ||||
| backgroundColor: Color | null = null // read in three.js WebGLBackground | backgroundColor: Color | null = null // read in three.js WebGLBackground | ||||
| @onChange2(RootScene.prototype.onBackgroundChange) | |||||
| @onChange3(RootScene.prototype.onBackgroundChange) | |||||
| @serialize() @uiImage('Background Image') | @serialize() @uiImage('Background Image') | ||||
| background: null | Color | ITexture | 'environment' = null | background: null | Color | ITexture | 'environment' = null | ||||
| /** | /** | ||||
| * The default environment map used when rendering materials in the scene | * The default environment map used when rendering materials in the scene | ||||
| */ | */ | ||||
| @uiImage('Environment') | @uiImage('Environment') | ||||
| @serialize() @onChange2(RootScene.prototype._onEnvironmentChange) | |||||
| @serialize() @onChange3(RootScene.prototype._onEnvironmentChange) | |||||
| environment: ITexture | null = null | environment: ITexture | null = null | ||||
| /** | /** | ||||
| */ | */ | ||||
| @uiConfig() @serialize() readonly defaultCamera: ICamera | @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 | // private _environmentLight?: IEnvironmentLight | ||||
| // required just because we don't want activeCamera to be null. | // required just because we don't want activeCamera to be null. | ||||
| } | } | ||||
| } | } | ||||
| 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') | // console.warn('environment changed') | ||||
| if (this.environment?.mapping === UVMapping) { | if (this.environment?.mapping === UVMapping) { | ||||
| this.environment.mapping = EquirectangularReflectionMapping // for PMREMGenerator | this.environment.mapping = EquirectangularReflectionMapping // for PMREMGenerator | ||||
| this.refreshUi?.() | 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.dispatchEvent({type: 'backgroundChanged', background: this.background, backgroundColor: this.backgroundColor}) | ||||
| this.setDirty({refreshScene: true, geometryChanged: false}) | this.setDirty({refreshScene: true, geometryChanged: false}) | ||||
| this.refreshUi?.() | this.refreshUi?.() |
| export type {AnimationOptions, KeyframeOptions, Easing} | 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 | // eslint-disable-next-line @typescript-eslint/naming-convention | ||||
| export const EasingFunctions = { | export const EasingFunctions = { |
| Vector3, | Vector3, | ||||
| EventListener2, | EventListener2, | ||||
| } from 'three' | } 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 {TViewerScreenShader} from '../postprocessing' | ||||
| import { | import { | ||||
| AddObjectOptions, | AddObjectOptions, | ||||
| export class ThreeViewer extends EventDispatcher<Record<IViewerEventTypes, IViewerEvent>> { | export class ThreeViewer extends EventDispatcher<Record<IViewerEventTypes, IViewerEvent>> { | ||||
| public static readonly VERSION = VERSION | public static readonly VERSION = VERSION | ||||
| public static readonly ConfigTypeSlug = 'vjson' | public static readonly ConfigTypeSlug = 'vjson' | ||||
| uiConfig!: UiObjectConfig | |||||
| declare uiConfig: UiObjectConfig | |||||
| static Console: IConsoleWrapper = { | static Console: IConsoleWrapper = { | ||||
| log: console.log.bind(console), | log: console.log.bind(console), | ||||
| this._canvas.style.height = size?.height ? size.height + 'px' : '100%' | 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.maxWidth = '100%' // this is upto the app to do. | ||||
| // this._canvas.style.maxHeight = '100%' | // 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. | // todo make an example for this. | ||||
| this._scene.modelRoot.traverse(callback) | this._scene.modelRoot.traverse(callback) | ||||
| } | } | ||||
| deleteImportedViewerConfigOnLoad = true | |||||
| /** | /** | ||||
| * Add an object to the scene model root. | * 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 | * If an imported scene model root is passed, it will be loaded with viewer configuration, unless importConfig is false | ||||
| const obj = <RootSceneImportResult>imported | const obj = <RootSceneImportResult>imported | ||||
| this._scene.loadModelRoot(obj, options) | this._scene.loadModelRoot(obj, options) | ||||
| if (obj.importedViewerConfig && options?.importConfig !== false) await this.importConfig(obj.importedViewerConfig) | 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 | return this._scene.modelRoot as T | ||||
| } | } | ||||
| this._scene.addObject(imported, options) | this._scene.addObject(imported, options) |