| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | ||||
| msaa: true, | msaa: true, | ||||
| plugins: [PickingPlugin], | plugins: [PickingPlugin], | ||||
| dropzone: { | |||||
| addOptions: { | |||||
| disposeSceneObjects: true, | |||||
| }, | |||||
| }, | |||||
| }) | }) | ||||
| const simplify = viewer.addPluginSync(MeshOptSimplifyModifierPlugin) | const simplify = viewer.addPluginSync(MeshOptSimplifyModifierPlugin) |
| { | { | ||||
| "name": "threepipe", | "name": "threepipe", | ||||
| "version": "0.0.30", | |||||
| "version": "0.0.31", | |||||
| "lockfileVersion": 3, | "lockfileVersion": 3, | ||||
| "requires": true, | "requires": true, | ||||
| "packages": { | "packages": { | ||||
| "": { | "": { | ||||
| "name": "threepipe", | "name": "threepipe", | ||||
| "version": "0.0.30", | |||||
| "version": "0.0.31", | |||||
| "license": "Apache-2.0", | "license": "Apache-2.0", | ||||
| "dependencies": { | "dependencies": { | ||||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz", | "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz", | ||||
| "@types/webxr": "^0.5.1", | "@types/webxr": "^0.5.1", | ||||
| "@types/wicg-file-system-access": "^2020.9.5", | "@types/wicg-file-system-access": "^2020.9.5", | ||||
| "stats.js": "^0.17.0", | "stats.js": "^0.17.0", | ||||
| "ts-browser-helpers": "^0.12.0", | |||||
| "ts-browser-helpers": "^0.13.0", | |||||
| "uiconfig.js": "^0.0.12" | "uiconfig.js": "^0.0.12" | ||||
| }, | }, | ||||
| "devDependencies": { | "devDependencies": { | ||||
| } | } | ||||
| }, | }, | ||||
| "node_modules/ts-browser-helpers": { | "node_modules/ts-browser-helpers": { | ||||
| "version": "0.12.0", | |||||
| "resolved": "https://registry.npmjs.org/ts-browser-helpers/-/ts-browser-helpers-0.12.0.tgz", | |||||
| "integrity": "sha512-lrXA3VZd9OvheHec+fQ3hVeSyLzQI0Bu3fH20/fQXH7Q4wYhZ2IwererEix/mn3j7Apo/W1XgYS8s8Xu7cCypQ==", | |||||
| "version": "0.13.0", | |||||
| "resolved": "https://registry.npmjs.org/ts-browser-helpers/-/ts-browser-helpers-0.13.0.tgz", | |||||
| "integrity": "sha512-n0qO5+Nr9pngVechioLzWueQWqOItYhyu3O0cvFxz/lPt2M9zipqyFTLg5LdNA7NJnvHxv588eUZHmzmLcEa4Q==", | |||||
| "dependencies": { | "dependencies": { | ||||
| "@types/wicg-file-system-access": "^2020.9.5" | "@types/wicg-file-system-access": "^2020.9.5" | ||||
| } | } |
| "@types/webxr": "^0.5.1", | "@types/webxr": "^0.5.1", | ||||
| "@types/wicg-file-system-access": "^2020.9.5", | "@types/wicg-file-system-access": "^2020.9.5", | ||||
| "stats.js": "^0.17.0", | "stats.js": "^0.17.0", | ||||
| "ts-browser-helpers": "^0.12.0", | |||||
| "ts-browser-helpers": "^0.13.0", | |||||
| "uiconfig.js": "^0.0.12" | "uiconfig.js": "^0.0.12" | ||||
| }, | }, | ||||
| "//": { | "//": { |
| { | { | ||||
| "name": "@threepipe/plugin-configurator", | "name": "@threepipe/plugin-configurator", | ||||
| "version": "0.1.0", | |||||
| "version": "0.1.1", | |||||
| "lockfileVersion": 3, | "lockfileVersion": 3, | ||||
| "requires": true, | "requires": true, | ||||
| "packages": { | "packages": { | ||||
| "": { | "": { | ||||
| "name": "@threepipe/plugin-configurator", | "name": "@threepipe/plugin-configurator", | ||||
| "version": "0.1.0", | |||||
| "version": "0.1.1", | |||||
| "license": "Apache-2.0", | "license": "Apache-2.0", | ||||
| "dependencies": { | "dependencies": { | ||||
| "threepipe": "file:./../../src/", | "threepipe": "file:./../../src/", |
| }, ['exr'], ['image/x-exr'], false), | }, ['exr'], ['image/x-exr'], false), | ||||
| new Importer(FBXLoader, ['fbx'], ['model/fbx'], true), | new Importer(FBXLoader, ['fbx'], ['model/fbx'], true), | ||||
| new Importer(ZipLoader, ['zip', 'glbz', 'gltfz'], ['application/zip', 'data:model/gltf+zip'], true), // gltfz and glbz are invented zip files with gltf/glb inside along with resources | |||||
| new Importer(ZipLoader, ['zip', 'glbz', 'gltfz'], ['application/zip', 'model/gltf+zip', 'model/zip'], true), // gltfz and glbz are invented zip files with gltf/glb inside along with resources | |||||
| new Importer(OBJLoader2 as any as Class<ILoader>, ['obj'], ['model/obj'], true), | new Importer(OBJLoader2 as any as Class<ILoader>, ['obj'], ['model/obj'], true), | ||||
| new Importer(MTLLoader2 as any as Class<ILoader>, ['mtl'], ['model/mtl'], false), | new Importer(MTLLoader2 as any as Class<ILoader>, ['mtl'], ['model/mtl'], false), | ||||
| new Importer<GLTFLoader2>(GLTFLoader2, ['gltf', 'glb', 'data:model/gltf'], ['model/gltf', 'model/gltf+json', 'model/gltf-binary'], true, (l, _, i) => l?.setup(this.viewer, i.extensions)), | |||||
| new Importer<GLTFLoader2>(GLTFLoader2, ['gltf', 'glb', 'data:model/gltf', 'data:model/glb'], ['model/gltf', 'model/gltf+json', 'model/gltf-binary', 'model/glb'], true, (l, _, i) => l?.setup(this.viewer, i.extensions)), | |||||
| new Importer(DRACOLoader2, ['drc'], ['model/mesh+draco'], true), | |||||
| new Importer(DRACOLoader2, ['drc'], ['model/mesh+draco', 'model/drc'], true), | |||||
| ] | ] | ||||
| this.importer.addImporter(...importers) | this.importer.addImporter(...importers) |
| import {shaderReplaceString} from '../../utils' | import {shaderReplaceString} from '../../utils' | ||||
| import {IMaterialUserData} from '../IMaterial' | import {IMaterialUserData} from '../IMaterial' | ||||
| // earlier it was ShaderMaterialEncodingSupport | |||||
| export class ExtendedShaderMaterial extends ShaderMaterial2 { | export class ExtendedShaderMaterial extends ShaderMaterial2 { | ||||
| declare ['constructor']: (typeof ExtendedShaderMaterial) & (typeof ShaderMaterial2) | declare ['constructor']: (typeof ExtendedShaderMaterial) & (typeof ShaderMaterial2) | ||||
| this.uniformsNeedUpdate = true | this.uniformsNeedUpdate = true | ||||
| } | } | ||||
| } | } | ||||
| onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D): void { | onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D): void { | ||||
| this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget() ?? renderer.getSize(new Vector2())) | this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget() ?? renderer.getSize(new Vector2())) | ||||
| x : Empty | x : Empty | ||||
| y : first 3 bits lut index, second 5 bits bevel radius | y : first 3 bits lut index, second 5 bits bevel radius | ||||
| z : material id (userData.gBufferData?.materialId, userData.matId) | z : material id (userData.gBufferData?.materialId, userData.matId) | ||||
| w : this field is for setting bits - lutEnable-0, tonemap-1, bloom-2, ssao(cast)-3 | |||||
| w : this field is for setting bits - lutEnable-0, tonemap-1, bloom-2, ssao(cast)-3, dof-4 | |||||
| */ | */ | ||||
| this.uniforms.flags.value.set(255, 255, 255, 255) | this.uniforms.flags.value.set(255, 255, 255, 255) |
| import {AnyFunction, getOrCall, safeSetProperty, ValOrFunc} from 'ts-browser-helpers' | |||||
| import {AnyFunction, getOrCall, objectHasOwn, safeSetProperty, ValOrFunc} from 'ts-browser-helpers' | |||||
| /** | /** | ||||
| * | * | ||||
| const cPropKey = !!propKey | const cPropKey = !!propKey | ||||
| const isThis = thisTarget | const isThis = thisTarget | ||||
| return (targetPrototype: any, propertyKey: string|symbol) => { | |||||
| return (targetPrototype: any, propertyKey: string|symbol, descriptor?: TypedPropertyDescriptor<any>) => { | |||||
| const getUniform = (target: any)=>{ | const getUniform = (target: any)=>{ | ||||
| const uniforms1 = isThis ? target : cUniforms ? uniforms : target.uniforms || target._uniforms || target.extraUniforms | const uniforms1 = isThis ? target : cUniforms ? uniforms : target.uniforms || target._uniforms || target.extraUniforms | ||||
| let propKey1 = cPropKey ? propKey : propertyKey | let propKey1 = cPropKey ? propKey : propertyKey | ||||
| } | } | ||||
| return a | return a | ||||
| } | } | ||||
| Object.defineProperty(targetPrototype, propertyKey, { | |||||
| const prop = { | |||||
| get() { | get() { | ||||
| return getUniform(this).value | return getUniform(this).value | ||||
| }, | }, | ||||
| }, | }, | ||||
| // configurable: true, | // configurable: true, | ||||
| // enumerable: true, | // enumerable: true, | ||||
| }) | |||||
| } as any | |||||
| // https://github.com/babel/babel/blob/909ed3473968c2ccd75f89e17c37ef4771cc3ff8/packages/babel-helpers/src/helpers/applyDecoratedDescriptor.ts#L11 | |||||
| if (descriptor) { | |||||
| if (objectHasOwn(descriptor, 'value')) delete descriptor.value | |||||
| if (objectHasOwn(descriptor, 'writable')) delete descriptor.writable | |||||
| if (objectHasOwn(descriptor, 'initializer')) delete (descriptor as any).initializer | |||||
| return Object.assign(descriptor, prop) | |||||
| } | |||||
| Object.defineProperty(targetPrototype, propertyKey, prop) | |||||
| } | } | ||||
| } | } | ||||
| // same logic as onChange in ts-browser-helpers. todo: loop through object prototype chain like in onChange? | // same logic as onChange in ts-browser-helpers. todo: loop through object prototype chain like in onChange? | ||||
| if (onChange.name) { | if (onChange.name) { | ||||
| const fn: AnyFunction = this[onChange.name] | const fn: AnyFunction = this[onChange.name] | ||||
| if (fn === onChange) | |||||
| if (fn && fn === onChange) | |||||
| onChange.call(this, ...params) | onChange.call(this, ...params) | ||||
| else if (fn.name.endsWith(`bound ${onChange.name}`)) | |||||
| else if (fn && fn.name.endsWith(`bound ${onChange.name}`)) | |||||
| fn(...params) | fn(...params) | ||||
| else onChange(...params) | else onChange(...params) | ||||
| } else onChange(...params) | } else onChange(...params) | ||||
| } | } | ||||
| // todo migrate to new decorators - https://2ality.com/2022/10/javascript-decorators.html | |||||
| /** | /** | ||||
| * Decorator to create a three.js style define in this.material or this and bind to a property. | * Decorator to create a three.js style define in this.material or this and bind to a property. | ||||
| * see also - {@link matDefineBool} | * see also - {@link matDefineBool} | ||||
| const cDefines = !!customDefines | const cDefines = !!customDefines | ||||
| const cPropKey = !!key | const cPropKey = !!key | ||||
| return (targetPrototype: any, propertyKey: string|symbol) => { | |||||
| return (targetPrototype: any, propertyKey: string|symbol, descriptor?: TypedPropertyDescriptor<any>) => { | |||||
| const getTarget = (mat: any)=>{ | const getTarget = (mat: any)=>{ | ||||
| const t = cDefines ? customDefines : mat.defines || mat._defines || mat.extraDefines | const t = cDefines ? customDefines : mat.defines || mat._defines || mat.extraDefines | ||||
| const p = cPropKey ? key : propertyKey | const p = cPropKey ? key : propertyKey | ||||
| return {t, p} | return {t, p} | ||||
| } | } | ||||
| Object.defineProperty(targetPrototype, propertyKey, { | |||||
| const prop = { | |||||
| get() { | get() { | ||||
| const {t, p} = getTarget(thisMat ? this : this.material) | const {t, p} = getTarget(thisMat ? this : this.material) | ||||
| let res = t[p] | let res = t[p] | ||||
| }, | }, | ||||
| // configurable: true, | // configurable: true, | ||||
| // enumerable: true, | // enumerable: true, | ||||
| }) | |||||
| } as any | |||||
| // https://github.com/babel/babel/blob/909ed3473968c2ccd75f89e17c37ef4771cc3ff8/packages/babel-helpers/src/helpers/applyDecoratedDescriptor.ts#L11 | |||||
| if (descriptor) { | |||||
| if (objectHasOwn(descriptor, 'value')) delete descriptor.value | |||||
| if (objectHasOwn(descriptor, 'writable')) delete descriptor.writable | |||||
| if (objectHasOwn(descriptor, 'initializer')) delete (descriptor as any).initializer | |||||
| return Object.assign(descriptor, prop) | |||||
| } | |||||
| Object.defineProperty(targetPrototype, propertyKey, prop) | |||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Binds a property to a value in an object. If the object is a string, it is used as a property name in `this`. | * Binds a property to a value in an object. If the object is a string, it is used as a property name in `this`. | ||||
| * | |||||
| * @param obj - object to bind to. If a string, it is used as a property name in `this`. If a function, it is called and the result is used as the object/string. | * @param obj - object to bind to. If a string, it is used as a property name in `this`. If a function, it is called and the result is used as the object/string. | ||||
| * @param key - key to bind to. If a string, it is used as a property name in `this`. If a function, it is called and the result is used as the key/string. | * @param key - key to bind to. If a string, it is used as a property name in `this`. If a function, it is called and the result is used as the key/string. | ||||
| * @param onChange - function to call when the value changes. If a string, it is used as a property name in `this` and called. If a function, it is called. The function is called with the following parameters: key, newVal | * @param onChange - function to call when the value changes. If a string, it is used as a property name in `this` and called. If a function, it is called. The function is called with the following parameters: key, newVal | ||||
| export function bindToValue({obj, key, onChange, processVal, invProcessVal}: {obj?: ValOrFunc<any>, key?: ValOrFunc<string | symbol>, onChange?: ((...args: any[]) => any)|string, processVal?: (newVal: any) => any, invProcessVal?: (val: any) => any}): PropertyDecorator { | export function bindToValue({obj, key, onChange, processVal, invProcessVal}: {obj?: ValOrFunc<any>, key?: ValOrFunc<string | symbol>, onChange?: ((...args: any[]) => any)|string, processVal?: (newVal: any) => any, invProcessVal?: (val: any) => any}): PropertyDecorator { | ||||
| const cPropKey = !!key | const cPropKey = !!key | ||||
| return (targetPrototype: any, propertyKey: string|symbol) => { | |||||
| return (targetPrototype: any, propertyKey: string|symbol, descriptor?: TypedPropertyDescriptor<any>) => { | |||||
| const getTarget = (_this: any)=>{ | const getTarget = (_this: any)=>{ | ||||
| let t = getOrCall(obj) || _this | let t = getOrCall(obj) || _this | ||||
| if (typeof t === 'string') t = _this[t] | if (typeof t === 'string') t = _this[t] | ||||
| const p = cPropKey ? getOrCall(key) || propertyKey : propertyKey | const p = cPropKey ? getOrCall(key) || propertyKey : propertyKey | ||||
| return {t, p} | return {t, p} | ||||
| } | } | ||||
| Object.defineProperty(targetPrototype, propertyKey, { | |||||
| const prop = { | |||||
| get() { | get() { | ||||
| const {t, p} = getTarget(this) | const {t, p} = getTarget(this) | ||||
| let res = t[p] | let res = t[p] | ||||
| }, | }, | ||||
| // configurable: true, | // configurable: true, | ||||
| // enumerable: true, | // enumerable: true, | ||||
| }) | |||||
| } as any | |||||
| // https://github.com/babel/babel/blob/909ed3473968c2ccd75f89e17c37ef4771cc3ff8/packages/babel-helpers/src/helpers/applyDecoratedDescriptor.ts#L11 | |||||
| if (descriptor) { | |||||
| if (objectHasOwn(descriptor, 'value')) delete descriptor.value | |||||
| if (objectHasOwn(descriptor, 'writable')) delete descriptor.writable | |||||
| if (objectHasOwn(descriptor, 'initializer')) delete (descriptor as any).initializer | |||||
| return Object.assign(descriptor, prop) | |||||
| } | |||||
| Object.defineProperty(targetPrototype, propertyKey, prop) | |||||
| } | } | ||||
| } | } |
| import {OrbitControls3} from '../three' | import {OrbitControls3} from '../three' | ||||
| export interface IViewerEvent extends BaseEvent, Partial<IAnimationLoopEvent> { | export interface IViewerEvent extends BaseEvent, Partial<IAnimationLoopEvent> { | ||||
| type: '*'|'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'renderEnabled'|'renderDisabled' | |||||
| eType?: '*'|'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'renderEnabled'|'renderDisabled' | |||||
| type: '*'|'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'removePlugin'|'renderEnabled'|'renderDisabled' | |||||
| eType?: '*'|'update'|'preRender'|'postRender'|'preFrame'|'postFrame'|'dispose'|'addPlugin'|'removePlugin'|'renderEnabled'|'renderDisabled' | |||||
| [p: string]: any | [p: string]: any | ||||
| } | } | ||||
| export type IViewerEventTypes = IViewerEvent['type'] | export type IViewerEventTypes = IViewerEvent['type'] | ||||
| const type = p.constructor.PluginType | const type = p.constructor.PluginType | ||||
| if (!this.plugins[type]) return | if (!this.plugins[type]) return | ||||
| await p.onRemove(this) | await p.onRemove(this) | ||||
| this.dispatchEvent({type: 'removePlugin', target: this, plugin: p}) | |||||
| delete this.plugins[type] | delete this.plugins[type] | ||||
| if (dispose) await p.dispose() // todo await? | if (dispose) await p.dispose() // todo await? | ||||
| this.setDirty(p) | this.setDirty(p) | ||||
| const type = p.constructor.PluginType | const type = p.constructor.PluginType | ||||
| if (!this.plugins[type]) return | if (!this.plugins[type]) return | ||||
| p.onRemove(this) | p.onRemove(this) | ||||
| this.dispatchEvent({type: 'removePlugin', target: this, plugin: p}) | |||||
| delete this.plugins[type] | delete this.plugins[type] | ||||
| if (dispose) p.dispose() | if (dispose) p.dispose() | ||||
| this.setDirty(p) | this.setDirty(p) |