| @@ -1,4 +1,4 @@ | |||
| export {PerspectiveCamera2} from './camera/PerspectiveCamera2' | |||
| export {PerspectiveCamera2, PerspectiveCamera0} from './camera/PerspectiveCamera2' | |||
| export {CameraView, type ICameraView} from './camera/CameraView' | |||
| export {ExtendedShaderMaterial} from './material/ExtendedShaderMaterial' | |||
| export {PhysicalMaterial, type PhysicalMaterialEventTypes, MeshStandardMaterial2} from './material/PhysicalMaterial' | |||
| @@ -7,9 +7,17 @@ export {UnlitMaterial, type UnlitMaterialEventTypes, MeshBasicMaterial2} from '. | |||
| export {UnlitLineMaterial, type UnlitLineMaterialEventTypes, LineBasicMaterial2} from './material/UnlitLineMaterial' | |||
| export {LineMaterial2, type LineMaterial2EventTypes} from './material/LineMaterial2' | |||
| export {LegacyPhongMaterial, type PhongMaterialEventTypes} from './material/LegacyPhongMaterial' | |||
| export {Mesh2} from './object/Mesh2' | |||
| export {BufferGeometry2} from './geometry/BufferGeometry2' | |||
| export {AmbientLight2} from './light/AmbientLight2' | |||
| export {DirectionalLight2} from './light/DirectionalLight2' | |||
| export {HemisphereLight2} from './light/HemisphereLight2' | |||
| export {PointLight2} from './light/PointLight2' | |||
| export {RectAreaLight2} from './light/RectAreaLight2' | |||
| export {SpotLight2} from './light/SpotLight2' | |||
| export {iObjectCommons} from './object/iObjectCommons' | |||
| export {iCameraCommons} from './object/iCameraCommons' | |||
| export {iLightCommons} from './object/iLightCommons' | |||
| export {iGeometryCommons} from './geometry/iGeometryCommons' | |||
| export {iMaterialCommons} from './material/iMaterialCommons' | |||
| export {upgradeTexture} from './ITexture' | |||
| @@ -23,3 +31,4 @@ export type {IObject3D, IObject3DEvent, IObjectSetDirtyOptions, IObjectProcessor | |||
| export type {IRenderManager, IRenderManagerOptions, IWebGLRenderer, IRenderManagerEventTypes, IAnimationLoopEvent, TThreeRendererMode, TThreeRendererModeUserData, IRenderManagerUpdateEvent, IRenderManagerEvent} from './IRenderer' | |||
| export type {IScene, ISceneEvent, ISceneEventTypes, ISceneSetDirtyOptions, AddObjectOptions, ISceneUserData, IWidget} from './IScene' | |||
| export type {ITexture, ITextureUserData, ITextureEvent, ITextureEventTypes} from './ITexture' | |||
| export type {ILight, ILightEvent, ILightEventTypes} from './light/ILight' | |||
| @@ -0,0 +1,73 @@ | |||
| import {AmbientLight, Color, ColorRepresentation} from 'three' | |||
| import {ILight, ILightEvent} from './ILight' | |||
| import {iLightCommons} from '../object/iLightCommons' | |||
| import {IObject3D} from '../IObject' | |||
| import {uiColor, uiPanelContainer, uiSlider, uiToggle} from 'uiconfig.js' | |||
| import {onChange3} from 'ts-browser-helpers' | |||
| @uiPanelContainer('Ambient Light') | |||
| export class AmbientLight2 extends AmbientLight implements ILight<undefined> { | |||
| assetType = 'light' as const | |||
| setDirty = iLightCommons.setDirty | |||
| refreshUi = iLightCommons.refreshUi | |||
| readonly isAmbientLight2 = true | |||
| @uiToggle('Enabled') | |||
| @onChange3('setDirty') | |||
| visible: boolean | |||
| @uiColor('Color', (that: AmbientLight2)=>({onChange: ()=>that.setDirty()})) | |||
| color: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @onChange3('setDirty') | |||
| intensity: number | |||
| constructor(color?: ColorRepresentation, intensity?: number) { | |||
| super(color, intensity) | |||
| iLightCommons.upgradeLight.call(this) | |||
| } | |||
| autoScale() { | |||
| console.warn('AutoScale not supported on Lights') | |||
| return this | |||
| } | |||
| autoCenter() { | |||
| console.warn('AutoCenter not supported on Lights') | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get lightObject(): this { | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: AmbientLight|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| import {Color, ColorRepresentation, DirectionalLight, DirectionalLightShadow, Euler, Vector3} from 'three' | |||
| import {ILight, ILightEvent} from './ILight' | |||
| import {iLightCommons} from '../object/iLightCommons' | |||
| import {IObject3D} from '../IObject' | |||
| import {uiColor, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' | |||
| import {onChange3} from 'ts-browser-helpers' | |||
| // todo: add LightShadow uiconfig | |||
| // todo: add Light section in the readme detailing these ...2 lights | |||
| @uiPanelContainer('Directional Light') | |||
| export class DirectionalLight2 extends DirectionalLight implements ILight<DirectionalLightShadow> { | |||
| assetType = 'light' as const | |||
| setDirty = iLightCommons.setDirty | |||
| refreshUi = iLightCommons.refreshUi | |||
| readonly isDirectionalLight2 = true | |||
| @uiToggle('Enabled') | |||
| @onChange3('setDirty') | |||
| visible: boolean | |||
| @uiColor('Color', (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | |||
| color: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @onChange3('setDirty') | |||
| intensity: number | |||
| @uiVector('Position', undefined, undefined, (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | |||
| readonly position: Vector3 | |||
| @uiVector('Rotation', undefined, undefined, (that: DirectionalLight2)=>({onChange: ()=>that.setDirty()})) | |||
| readonly rotation: Euler | |||
| @uiToggle('Cast Shadow') | |||
| @onChange3('setDirty') | |||
| castShadow: boolean | |||
| constructor(color?: ColorRepresentation, intensity?: number) { | |||
| super(color, intensity) | |||
| this.target.position.set(0, 0, -1) // because of GLTF spec: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_lights_punctual | |||
| this.add(this.target) // todo: make sure the child isn't exported in gltf | |||
| iLightCommons.upgradeLight.call(this) | |||
| } | |||
| autoScale() { | |||
| console.warn('AutoScale not supported on Lights') | |||
| return this | |||
| } | |||
| autoCenter() { | |||
| console.warn('AutoCenter not supported on Lights') | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get lightObject(): this { | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: DirectionalLight|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| import {Color, ColorRepresentation, HemisphereLight, Vector3} from 'three' | |||
| import {ILight, ILightEvent} from './ILight' | |||
| import {iLightCommons} from '../object/iLightCommons' | |||
| import {IObject3D} from '../IObject' | |||
| import {uiColor, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' | |||
| import {onChange3} from 'ts-browser-helpers' | |||
| @uiPanelContainer('Hemisphere Light') | |||
| export class HemisphereLight2 extends HemisphereLight implements ILight<undefined> { | |||
| assetType = 'light' as const | |||
| setDirty = iLightCommons.setDirty | |||
| refreshUi = iLightCommons.refreshUi | |||
| readonly isHemisphereLight2 = true | |||
| @uiToggle('Enabled') | |||
| @onChange3('setDirty') | |||
| visible: boolean | |||
| @uiColor('Sky Color', (that: HemisphereLight2)=>({onChange: ()=>that.setDirty()})) | |||
| color: Color | |||
| @uiColor('Ground Color', (that: HemisphereLight2)=>({onChange: ()=>that.setDirty()})) | |||
| groundColor: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @onChange3('setDirty') | |||
| intensity: number | |||
| @uiVector('Position', undefined, undefined, (that: HemisphereLight2)=>({onChange: ()=>that.setDirty()})) | |||
| readonly position: Vector3 | |||
| constructor(skyColor?: ColorRepresentation, groundColor?: ColorRepresentation, intensity?: number) { | |||
| super(skyColor, groundColor, intensity) | |||
| iLightCommons.upgradeLight.call(this) | |||
| } | |||
| autoScale() { | |||
| console.warn('AutoScale not supported on Lights') | |||
| return this | |||
| } | |||
| autoCenter() { | |||
| console.warn('AutoCenter not supported on Lights') | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get lightObject(): this { | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: HemisphereLight|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,52 @@ | |||
| import {Light, LightShadow, Object3D} from 'three' | |||
| import {IObject3D, IObject3DEvent, IObject3DEventTypes, IObject3DUserData} from '../IObject' | |||
| export interface ILight< | |||
| TShadowSupport extends LightShadow | undefined = LightShadow | undefined, | |||
| E extends ILightEvent = ILightEvent, | |||
| ET extends ILightEventTypes = ILightEventTypes | |||
| // @ts-expect-error update three-ts-types | |||
| > extends Light<TShadowSupport, E, ET>, IObject3D<E, ET> { | |||
| assetType: 'light' | |||
| readonly isLight: true | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| lightObject: this | |||
| // Note: for userData: add _ in front of for private use, which is preserved while cloning but not serialisation, and __ for private use, which is not preserved while cloning and serialisation | |||
| userData: IObject3DUserData | |||
| /** | |||
| * @param removeFromParent - remove from parent. Default true | |||
| */ | |||
| dispose(removeFromParent?: boolean): void; | |||
| target?: Object3D | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse(callback: (object: IObject3D) => void): void | |||
| traverseVisible(callback: (object: IObject3D) => void): void | |||
| traverseAncestors(callback: (object: IObject3D) => void): void | |||
| 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, worldSpace?: boolean, ...args: any[]): this | |||
| clone(recursive?: boolean): this | |||
| add(...object: IObject3D[]): this | |||
| remove(...object: IObject3D[]): this | |||
| parent: IObject3D | null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| export type ILightEventTypes = IObject3DEventTypes | 'lightUpdate'// | string | |||
| export type ILightEvent = Omit<IObject3DEvent, 'type'> & { | |||
| type: ILightEventTypes | |||
| light?: ILight | null | |||
| // change?: string | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| import {Color, ColorRepresentation, PointLight, PointLightShadow, Vector3} from 'three' | |||
| import {ILight, ILightEvent} from './ILight' | |||
| import {iLightCommons} from '../object/iLightCommons' | |||
| import {IObject3D} from '../IObject' | |||
| import {uiColor, uiNumber, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' | |||
| import {onChange3} from 'ts-browser-helpers' | |||
| @uiPanelContainer('Point Light') | |||
| export class PointLight2 extends PointLight implements ILight<PointLightShadow> { | |||
| assetType = 'light' as const | |||
| setDirty = iLightCommons.setDirty | |||
| refreshUi = iLightCommons.refreshUi | |||
| readonly isPointLight2 = true | |||
| @uiToggle('Enabled') | |||
| @onChange3('setDirty') | |||
| visible: boolean | |||
| @uiColor('Color', (that: PointLight2)=>({onChange: ()=>that.setDirty()})) | |||
| color: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @onChange3('setDirty') | |||
| intensity: number | |||
| @uiNumber('Distance') | |||
| @onChange3('setDirty') | |||
| distance: number | |||
| @uiNumber('Decay') | |||
| @onChange3('setDirty') | |||
| decay: number | |||
| @uiVector('Position', undefined, undefined, (that: PointLight2)=>({onChange: ()=>that.setDirty()})) | |||
| readonly position: Vector3 | |||
| @uiToggle('Cast Shadow') | |||
| @onChange3('setDirty') | |||
| castShadow: boolean | |||
| constructor(color?: ColorRepresentation, intensity?: number, distance?: number, decay?: number) { | |||
| super(color, intensity, distance, decay) | |||
| iLightCommons.upgradeLight.call(this) | |||
| } | |||
| autoScale() { | |||
| console.warn('AutoScale not supported on Lights') | |||
| return this | |||
| } | |||
| autoCenter() { | |||
| console.warn('AutoCenter not supported on Lights') | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get lightObject(): this { | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: PointLight|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,82 @@ | |||
| import {Color, ColorRepresentation, RectAreaLight} from 'three' | |||
| import {ILight, ILightEvent} from './ILight' | |||
| import {iLightCommons} from '../object/iLightCommons' | |||
| import {IObject3D} from '../IObject' | |||
| import {uiColor, uiNumber, uiPanelContainer, uiSlider, uiToggle} from 'uiconfig.js' | |||
| import {onChange3} from 'ts-browser-helpers' | |||
| @uiPanelContainer('RectArea Light') | |||
| export class RectAreaLight2 extends RectAreaLight implements ILight<undefined> { | |||
| assetType = 'light' as const | |||
| setDirty = iLightCommons.setDirty | |||
| refreshUi = iLightCommons.refreshUi | |||
| readonly isRectAreaLight2 = true | |||
| @uiToggle('Enabled') | |||
| @onChange3('setDirty') | |||
| visible: boolean | |||
| @uiColor('Color', (that: RectAreaLight2)=>({onChange: ()=>that.setDirty()})) | |||
| color: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @onChange3('setDirty') | |||
| intensity: number | |||
| @uiNumber('Width') | |||
| @onChange3('setDirty') | |||
| width: number | |||
| @uiNumber('Height') | |||
| @onChange3('setDirty') | |||
| height: number | |||
| @uiNumber('Power') | |||
| @onChange3('setDirty') | |||
| power: number | |||
| constructor(color?: ColorRepresentation, intensity?: number, width?: number, height?: number) { | |||
| super(color, intensity, width, height) | |||
| iLightCommons.upgradeLight.call(this) | |||
| } | |||
| autoScale() { | |||
| console.warn('AutoScale not supported on Lights') | |||
| return this | |||
| } | |||
| autoCenter() { | |||
| console.warn('AutoCenter not supported on Lights') | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get lightObject(): this { | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: RectAreaLight|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,97 @@ | |||
| import {Color, ColorRepresentation, Euler, SpotLight, SpotLightShadow, Vector3} from 'three' | |||
| import {ILight, ILightEvent} from './ILight' | |||
| import {iLightCommons} from '../object/iLightCommons' | |||
| import {IObject3D} from '../IObject' | |||
| import {uiColor, uiInput, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' | |||
| import {onChange3} from 'ts-browser-helpers' | |||
| @uiPanelContainer('Spot Light') | |||
| export class SpotLight2 extends SpotLight implements ILight<SpotLightShadow> { | |||
| assetType = 'light' as const | |||
| setDirty = iLightCommons.setDirty | |||
| refreshUi = iLightCommons.refreshUi | |||
| readonly isSpotLight2 = true | |||
| @uiToggle('Enabled') | |||
| @onChange3('setDirty') | |||
| visible: boolean | |||
| @uiColor('Color', (that: SpotLight2)=>({onChange: ()=>that.setDirty()})) | |||
| color: Color | |||
| @uiSlider('Intensity', [0, 30], 0.01) | |||
| @onChange3('setDirty') | |||
| intensity: number | |||
| @uiSlider('Angle', [0, 2], 0.01) | |||
| @onChange3('setDirty') | |||
| angle: number | |||
| @uiSlider('Penumbra', [0, 0.9999], 0.01) | |||
| @onChange3('setDirty') | |||
| penumbra: number | |||
| @uiInput('Distance') | |||
| @onChange3('setDirty') | |||
| distance: number | |||
| @uiInput('Decay') | |||
| @onChange3('setDirty') | |||
| decay: number | |||
| @uiVector('Position', undefined, undefined, (that: SpotLight2)=>({onChange: ()=>that.setDirty()})) | |||
| readonly position: Vector3 | |||
| @uiVector('Rotation', undefined, undefined, (that: SpotLight2)=>({onChange: ()=>that.setDirty()})) | |||
| readonly rotation: Euler | |||
| @uiToggle('Cast Shadow') | |||
| @onChange3('setDirty') | |||
| castShadow: boolean | |||
| constructor(color?: ColorRepresentation, intensity?: number, distance?: number, | |||
| angle?: number, | |||
| penumbra?: number, | |||
| decay?: number) { | |||
| super(color, intensity, distance, angle, penumbra, decay) | |||
| this.target.position.set(0, 0, -1) // because of GLTF spec: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_lights_punctual | |||
| this.add(this.target) // todo: make sure the child isn't exported in gltf | |||
| iLightCommons.upgradeLight.call(this) | |||
| } | |||
| autoScale() { | |||
| console.warn('AutoScale not supported on Lights') | |||
| return this | |||
| } | |||
| autoCenter() { | |||
| console.warn('AutoCenter not supported on Lights') | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get lightObject(): this { | |||
| return this | |||
| } | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: SpotLight|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,51 @@ | |||
| import {Mesh} from 'three' | |||
| import {IObject3D} from '../IObject' | |||
| import {iObjectCommons} from './iObjectCommons' | |||
| import {IMaterial} from '../IMaterial' | |||
| import {IGeometry} from '../IGeometry' | |||
| import {ILightEvent} from '../light/ILight' | |||
| export class Mesh2< | |||
| TGeometry extends IGeometry = IGeometry, | |||
| TMaterial extends IMaterial | IMaterial[] = IMaterial | IMaterial[] | |||
| > extends Mesh<TGeometry, TMaterial> implements IObject3D { | |||
| assetType = 'model' as const | |||
| setDirty = iObjectCommons.setDirty | |||
| refreshUi = iObjectCommons.refreshUi | |||
| material: TMaterial | |||
| readonly materials: IMaterial[] | |||
| geometry: TGeometry | |||
| /** | |||
| * @deprecated use `this` instead | |||
| */ | |||
| get modelObject(): this { | |||
| return this | |||
| } | |||
| constructor(geometry?: TGeometry, material?: TMaterial) { | |||
| super(geometry, material) | |||
| iObjectCommons.upgradeObject3D.call(this) | |||
| } | |||
| // region inherited type fixes | |||
| // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 | |||
| traverse: (callback: (object: IObject3D) => void) => void | |||
| traverseVisible: (callback: (object: IObject3D) => void) => void | |||
| traverseAncestors: (callback: (object: IObject3D) => void) => void | |||
| 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: Mesh2|IObject3D, recursive?: boolean, ...args: any[]) => this | |||
| clone: (recursive?: boolean) => this | |||
| remove: (...object: IObject3D[]) => this | |||
| dispatchEvent: (event: ILightEvent) => void | |||
| parent: null | |||
| children: IObject3D[] | |||
| dispose: (removeFromParent?: boolean) => void | |||
| // endregion | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| import {ILight} from '../light/ILight' | |||
| import {IObjectProcessor, IObjectSetDirtyOptions} from '../IObject' | |||
| import {iObjectCommons} from './iObjectCommons' | |||
| export const iLightCommons = { | |||
| setDirty: function(this: ILight, options?: IObjectSetDirtyOptions): void { | |||
| this.dispatchEvent({bubbleToParent: true, ...options, type: 'lightUpdate', light: this, object: this}) // this sets sceneUpdate in root scene | |||
| iObjectCommons.setDirty.call(this, options) | |||
| }, | |||
| upgradeLight: upgradeLight, | |||
| refreshUi: iObjectCommons.refreshUi, | |||
| } | |||
| /** | |||
| * Converts three.js Light to ILight setup object events, adds utility methods, and runs objectProcessor. | |||
| * @param parent | |||
| * @param objectProcessor | |||
| */ | |||
| function upgradeLight(this: ILight, parent?: ILight|undefined, objectProcessor?: IObjectProcessor): void { | |||
| if (!this) return | |||
| iObjectCommons.upgradeObject3D.call(this, parent, objectProcessor) | |||
| } | |||
| @@ -2,12 +2,13 @@ import {Event, Mesh, Vector3} from 'three' | |||
| import {IMaterial} from '../IMaterial' | |||
| import {objectHasOwn} from 'ts-browser-helpers' | |||
| import {IObject3D, IObject3DEvent, IObjectProcessor, IObjectSetDirtyOptions} from '../IObject' | |||
| import {copyObject3DUserData} from '../../utils' | |||
| import {copyObject3DUserData} from '../../utils/serialization' | |||
| import {IGeometry, IGeometryEvent} from '../IGeometry' | |||
| import {Box3B} from '../../three' | |||
| import {Box3B} from '../../three/math/Box3B' | |||
| import {makeIObject3DUiConfig} from './IObjectUi' | |||
| import {iGeometryCommons} from '../geometry/iGeometryCommons' | |||
| import {iMaterialCommons} from '../material/iMaterialCommons' | |||
| import {ILight} from '../light/ILight' | |||
| export const iObjectCommons = { | |||
| setDirty: function(this: IObject3D, options?: IObjectSetDirtyOptions): void { | |||
| @@ -37,35 +38,35 @@ export const iObjectCommons = { | |||
| } | |||
| const scale = autoScaleRadius / radius | |||
| // this.scale.multiplyScalar(20 / radius) | |||
| if (isFinite(scale)) { // NaN when radius is 0 | |||
| if (this.userData.pseudoCentered) { | |||
| this.children.forEach(child => { | |||
| child.scale.multiplyScalar(scale) | |||
| }) | |||
| } else | |||
| this.scale.multiplyScalar(scale) | |||
| if (isCentered || this.userData.isCentered) this.position.multiplyScalar(scale) | |||
| this.traverse((obj)=>{ | |||
| const l = obj as any | |||
| if (l.isLight && l.shadow?.camera?.right) { | |||
| l.shadow.camera.right *= scale | |||
| l.shadow.camera.left *= scale | |||
| l.shadow.camera.top *= scale | |||
| l.shadow.camera.bottom *= scale | |||
| obj.setDirty() | |||
| } | |||
| if (l.isCamera && l.right) { | |||
| l.right *= scale | |||
| l.left *= scale | |||
| l.top *= scale | |||
| l.bottom *= scale | |||
| obj.setDirty() | |||
| } | |||
| if (!isFinite(scale)) return this // NaN when radius is 0 | |||
| if (this.userData.pseudoCentered) { | |||
| this.children.forEach(child => { | |||
| child.scale.multiplyScalar(scale) | |||
| }) | |||
| this.userData.autoScaled = true | |||
| this.userData.autoScaleRadius = autoScaleRadius | |||
| if (setDirty) this.setDirty({change: 'autoScale'}) | |||
| } | |||
| } else | |||
| this.scale.multiplyScalar(scale) | |||
| if (isCentered || this.userData.isCentered) this.position.multiplyScalar(scale) | |||
| this.traverse((obj) => { | |||
| const l = obj as any | |||
| if (l.isLight && l.shadow?.camera?.right) { | |||
| l.shadow.camera.right *= scale | |||
| l.shadow.camera.left *= scale | |||
| l.shadow.camera.top *= scale | |||
| l.shadow.camera.bottom *= scale | |||
| obj.setDirty() | |||
| } | |||
| if (l.isCamera && l.right) { | |||
| l.right *= scale | |||
| l.left *= scale | |||
| l.top *= scale | |||
| l.bottom *= scale | |||
| obj.setDirty() | |||
| } | |||
| }) | |||
| this.userData.autoScaled = true | |||
| this.userData.autoScaleRadius = autoScaleRadius | |||
| if (setDirty) this.setDirty({change: 'autoScale'}) | |||
| return this | |||
| }, | |||
| @@ -272,7 +273,9 @@ export const iObjectCommons = { | |||
| return clone | |||
| }, | |||
| copy: (superCopy: IObject3D['copy']): IObject3D['copy'] => | |||
| function(this: IObject3D, source: IObject3D, ...args): IObject3D { | |||
| function(this: IObject3D|ILight, source: IObject3D, ...args): IObject3D { | |||
| const lightTarget = this.isLight ? (this as ILight).target : null | |||
| const userData = source.userData | |||
| source.userData = {} | |||
| @@ -282,6 +285,13 @@ export const iObjectCommons = { | |||
| source.userData = userData | |||
| copyObject3DUserData(this.userData, source.userData) // todo: do same for object.toJSON() | |||
| if (lightTarget && (this as ILight).target) { // For eg DirectionalLight2 | |||
| lightTarget.position.copy((this as ILight).target!.position) | |||
| lightTarget.updateMatrixWorld() | |||
| ;(this as ILight).target = lightTarget // because t is a child and because of UI. | |||
| } | |||
| return this | |||
| }, | |||
| add: (superAdd: IObject3D['add']): IObject3D['add'] => | |||
| @@ -320,7 +330,7 @@ export const iObjectCommons = { | |||
| * @param parent | |||
| * @param objectProcessor | |||
| */ | |||
| function upgradeObject3D(this: IObject3D, parent?: IObject3D|undefined, objectProcessor?: IObjectProcessor): void { // parent is the root Object3DModel. | |||
| function upgradeObject3D(this: IObject3D, parent?: IObject3D|undefined, objectProcessor?: IObjectProcessor): void { | |||
| if (!this) return | |||
| // console.log('upgradeObject3D', this, parent, objectProcessor) | |||
| // if (this.__disposed) { | |||
| @@ -332,6 +342,7 @@ function upgradeObject3D(this: IObject3D, parent?: IObject3D|undefined, objectPr | |||
| // not checking assetType but custom var __objectSetup because its required in types sometimes, check PerspectiveCamera2 | |||
| // if (this.assetType) return | |||
| if (this.userData.__objectSetup) return | |||
| this.userData.__objectSetup = true | |||
| @@ -453,4 +464,3 @@ function upgradeObject3D(this: IObject3D, parent?: IObject3D|undefined, objectPr | |||
| this.objectProcessor?.processObject(this) | |||
| } | |||