| * @param eventOptions | * @param eventOptions | ||||
| */ | */ | ||||
| setViewToMain(eventOptions: Pick<ICameraEventMap['setView'], 'ui'>): void | setViewToMain(eventOptions: Pick<ICameraEventMap['setView'], 'ui'>): void | ||||
| /** | |||||
| * Set the canvas which is used as dom element in controls, etc. | |||||
| * This is done by the viewer/scene when main camera is changed | |||||
| * @param canvas | |||||
| * @param refresh | |||||
| */ | |||||
| setCanvas(canvas: HTMLCanvasElement|undefined, refresh?: boolean): void; // todo make optional | |||||
| // region inherited type fixes | // region inherited type fixes | ||||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | ||||
| camera?: ICamera | null | camera?: ICamera | null | ||||
| bubbleToParent: boolean | bubbleToParent: boolean | ||||
| // object: IObject3D | // object: IObject3D | ||||
| // todo | |||||
| } | } | ||||
| cameraUpdate: { | cameraUpdate: { | ||||
| ui?: boolean | ui?: boolean |
| export interface ICameraControls<TE extends ICameraControlsEventMap = ICameraControlsEventMap> extends IUiConfigContainer<void, 'panel'>, EventDispatcher<TE> { | export interface ICameraControls<TE extends ICameraControlsEventMap = ICameraControlsEventMap> extends IUiConfigContainer<void, 'panel'>, EventDispatcher<TE> { | ||||
| object: Object3D | object: Object3D | ||||
| enabled: boolean | enabled: boolean | ||||
| domElement?: HTMLElement | Document; | |||||
| dispose(): void | dispose(): void | ||||
| refreshCameraControls(setDirty = true): void { | refreshCameraControls(setDirty = true): void { | ||||
| if (!this._controlsCtors) return // class not initialized | if (!this._controlsCtors) return // class not initialized | ||||
| if (this._controls) { | if (this._controls) { | ||||
| if (this._currentControlsMode !== this.controlsMode || this !== this._controls.object) { // in-case camera changed or mode changed | |||||
| if (this._currentControlsMode !== this.controlsMode || | |||||
| this !== this._controls.object || | |||||
| this._controls.domElement && this._canvas !== this._controls.domElement | |||||
| ) { // in-case camera changed or mode changed | |||||
| this._disposeCameraControls() | this._disposeCameraControls() | ||||
| this._initCameraControls() | this._initCameraControls() | ||||
| } | } | ||||
| // iObjectCommons.dispose and dispatch event dispose is called automatically because of updateObject3d | // iObjectCommons.dispose and dispatch event dispose is called automatically because of updateObject3d | ||||
| } | } | ||||
| setCanvas(canvas: HTMLCanvasElement|undefined, refresh = true) { | |||||
| this._canvas = canvas | |||||
| if (!refresh) return | |||||
| this.refreshCameraControls() | |||||
| this.refreshAspect(false) | |||||
| } | |||||
| // endregion | // endregion | ||||
| // region ui | // region ui |
| refreshCameraControls(setDirty = true): void { | refreshCameraControls(setDirty = true): void { | ||||
| if (!this._controlsCtors) return // class not initialized | if (!this._controlsCtors) return // class not initialized | ||||
| if (this._controls) { | if (this._controls) { | ||||
| if (this._currentControlsMode !== this.controlsMode || this !== this._controls.object) { // in-case camera changed or mode changed | |||||
| if (this._currentControlsMode !== this.controlsMode || | |||||
| this !== this._controls.object || | |||||
| this._controls.domElement && this._canvas !== this._controls.domElement | |||||
| ) { // in-case camera changed or mode changed | |||||
| this._disposeCameraControls() | this._disposeCameraControls() | ||||
| this._initCameraControls() | this._initCameraControls() | ||||
| } | } | ||||
| // iObjectCommons.dispose and dispatch event dispose is called automatically because of updateObject3d | // iObjectCommons.dispose and dispatch event dispose is called automatically because of updateObject3d | ||||
| } | } | ||||
| setCanvas(canvas: HTMLCanvasElement|undefined, refresh = true) { | |||||
| this._canvas = canvas | |||||
| if (!refresh) return | |||||
| this.refreshCameraControls() | |||||
| this.refreshAspect(false) | |||||
| } | |||||
| // endregion | // endregion | ||||
| // region ui | // region ui |
| this.dispatchEvent({...options, type: 'cameraUpdate', bubbleToParent: true}) // this sets dirty in the viewer | this.dispatchEvent({...options, type: 'cameraUpdate', bubbleToParent: true}) // this sets dirty in the viewer | ||||
| iObjectCommons.setDirty.call(this, {refreshScene: false, ...options}) | iObjectCommons.setDirty.call(this, {refreshScene: false, ...options}) | ||||
| }, | }, | ||||
| activateMain: function(this: ICamera, options: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'> = {}, _internal = false, _refresh = true): void { | |||||
| activateMain: function(this: ICamera, options: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'> = {}, _internal = false, _refresh = true, canvas?: HTMLCanvasElement): void { | |||||
| if (!_internal) { | if (!_internal) { | ||||
| if (options.camera === null) return this.deactivateMain(options, _internal, _refresh) | if (options.camera === null) return this.deactivateMain(options, _internal, _refresh) | ||||
| return this.dispatchEvent({ | return this.dispatchEvent({ | ||||
| this.userData.__isMainCamera = true | this.userData.__isMainCamera = true | ||||
| this.userData.__lastScale = this.scale.clone() | this.userData.__lastScale = this.scale.clone() | ||||
| this.scale.divide(this.getWorldScale(new Vector3())) // make unit scale, for near far and all | this.scale.divide(this.getWorldScale(new Vector3())) // make unit scale, for near far and all | ||||
| if (_refresh) { | |||||
| if (canvas) this.setCanvas(canvas, _refresh) | |||||
| else if (_refresh) { | |||||
| this.refreshCameraControls(false) | this.refreshCameraControls(false) | ||||
| this.refreshAspect(false) | |||||
| } | } | ||||
| this.setDirty({change: 'activateMain', ...options}) | this.setDirty({change: 'activateMain', ...options}) | ||||
| // console.log({...this._camera.modelObject.position}) | // console.log({...this._camera.modelObject.position}) | ||||
| }, | }, | ||||
| deactivateMain: function(this: ICamera, options: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'> = {}, _internal = false, _refresh = true): void { | |||||
| deactivateMain: function(this: ICamera, options: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'> = {}, _internal = false, _refresh = true, clearCanvas = false): void { | |||||
| if (!_internal) return this.dispatchEvent({ | if (!_internal) return this.dispatchEvent({ | ||||
| type: 'activateMain', ...options, | type: 'activateMain', ...options, | ||||
| camera: null, | camera: null, | ||||
| this.scale.copy(this.userData.__lastScale) | this.scale.copy(this.userData.__lastScale) | ||||
| delete this.userData.__lastScale | delete this.userData.__lastScale | ||||
| } | } | ||||
| if (clearCanvas) this.setCanvas(undefined, _refresh) | |||||
| else if (_refresh) this.refreshCameraControls(false) | |||||
| if (_refresh) { | if (_refresh) { | ||||
| this.refreshCameraControls(false) | this.refreshCameraControls(false) | ||||
| } | } |
| export {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' | export {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' | ||||
| export * from 'three/examples/jsm/utils/BufferGeometryUtils.js' | export * from 'three/examples/jsm/utils/BufferGeometryUtils.js' | ||||
| export type {Event, EventListener} from 'three' | |||||
| export type {Event, EventListener} from 'three' | |||||
| import type {Event} from 'three' | |||||
| // todo export from three | |||||
| export type EventListener2<TEventType extends string, TEventMap extends Record<TEventType, any>, TTarget> = ( | |||||
| event: TEventMap[TEventType] & Event<TEventType, TTarget>, | |||||
| ) => void |
| IMaterial, | IMaterial, | ||||
| IObject3D, | IObject3D, | ||||
| IObjectProcessor, | IObjectProcessor, | ||||
| ISceneEventMap, | |||||
| ITexture, | ITexture, | ||||
| OrthographicCamera2, | OrthographicCamera2, | ||||
| PerspectiveCamera2, | PerspectiveCamera2, | ||||
| import {TonemapPlugin} from '../plugins/postprocessing/TonemapPlugin' | import {TonemapPlugin} from '../plugins/postprocessing/TonemapPlugin' | ||||
| import {VERSION} from './version' | import {VERSION} from './version' | ||||
| import {OrbitControls3} from '../three' | import {OrbitControls3} from '../three' | ||||
| import {EventListener2} from '../three/Threejs' | |||||
| // todo make proper event map | // todo make proper event map | ||||
| export interface IViewerEvent extends BaseEvent, Partial<IAnimationLoopEvent> { | export interface IViewerEvent extends BaseEvent, Partial<IAnimationLoopEvent> { | ||||
| await tr.exportFile(blob, name) | await tr.exportFile(blob, name) | ||||
| } | } | ||||
| private _setActiveCameraView(event: any = {}): void { | |||||
| private _setActiveCameraView: EventListener2<'setView'|'activateMain', ISceneEventMap, RootScene> = (event) => { | |||||
| if (event.type === 'setView') { | if (event.type === 'setView') { | ||||
| if (!event.camera) { | if (!event.camera) { | ||||
| this.console.warn('Cannot find camera', event) | this.console.warn('Cannot find camera', event) | ||||
| } | } | ||||
| const camera = this._scene.mainCamera | const camera = this._scene.mainCamera | ||||
| camera.setViewFromCamera(event.camera) // default is worldSpace | camera.setViewFromCamera(event.camera) // default is worldSpace | ||||
| } else if (event.type === 'activateMain') | |||||
| } else if (event.type === 'activateMain') { | |||||
| event.camera?.setCanvas(this._canvas, false) | |||||
| // this._scene.mainCamera.setCanvas(undefined, false) // todo is this required? | |||||
| this._scene.mainCamera = event.camera || undefined // event.camera should have been upgraded when added to the scene. | this._scene.mainCamera = event.camera || undefined // event.camera should have been upgraded when added to the scene. | ||||
| } | |||||
| this._scene.mainCamera = event.camera || undefined // event.camera should have been upgraded when added to the scene. | |||||
| } | } | ||||
| private _resolvePluginOrClass<T extends IViewerPlugin>(plugin: T | Class<T>, ...args: ConstructorParameters<Class<T>>): T|undefined { | private _resolvePluginOrClass<T extends IViewerPlugin>(plugin: T | Class<T>, ...args: ConstructorParameters<Class<T>>): T|undefined { |