瀏覽代碼

Fix gltf encryption, fix ktx2 texture cloning, some type changes, minor fixes.

master
Palash Bansal 2 年之前
父節點
當前提交
755ab0798f
沒有連結到貢獻者的電子郵件帳戶。

+ 1
- 1
.github/workflows/deploy-pages.yml 查看文件

cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-data cache-dependency-path: '**/package-lock.json' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-data
- run: npm ci # this will also run `npm run prepare` which will build # todo use --cache .npm - run: npm ci # this will also run `npm run prepare` which will build # todo use --cache .npm
- run: npm run docs-all
- run: npm run docs
- run: mkdir _site - run: mkdir _site
- run: mv -t _site src docs dist examples README.md LICENSE index.html - run: mv -t _site src docs dist examples README.md LICENSE index.html
- run: mkdir -p _site/plugins - run: mkdir -p _site/plugins

+ 2
- 2
examples/ktx2-load/script.ts 查看文件

dropzone: { dropzone: {
allowedExtensions: ['ktx2'], allowedExtensions: ['ktx2'],
}, },
plugins: [KTX2LoadPlugin],
}) })
viewer.addPluginSync(KTX2LoadPlugin)


viewer.scene.setBackgroundColor('#555555') viewer.scene.setBackgroundColor('#555555')




// Listen to when a file is dropped // Listen to when a file is dropped
viewer.assetManager.addEventListener('loadAsset', (e)=>{ viewer.assetManager.addEventListener('loadAsset', (e)=>{
if (!e.data.isTexture) return
if (!e.data?.isTexture) return
const texture = e.data as ITexture const texture = e.data as ITexture
texture.colorSpace = SRGBColorSpace texture.colorSpace = SRGBColorSpace
const material = new UnlitMaterial({ const material = new UnlitMaterial({

+ 6
- 0
examples/material-configurator-plugin/index.html 查看文件

margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
} }

#gridItemList{
/*because of the code preview button*/
top: 50px !important;
height: calc(100% - 50px) !important;
}
</style> </style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script> <script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>

+ 10
- 2
examples/material-configurator-plugin/script.ts 查看文件

import {_testFinish, FrameFadePlugin, IObject3D, PickingPlugin, SSAAPlugin, ThreeViewer} from 'threepipe'
import {
_testFinish,
FrameFadePlugin,
IObject3D,
LoadingScreenPlugin,
PickingPlugin,
SSAAPlugin,
ThreeViewer,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'
import {MaterialConfiguratorPlugin} from '@threepipe/plugin-configurator' import {MaterialConfiguratorPlugin} from '@threepipe/plugin-configurator'


const viewer = new ThreeViewer({ const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement, canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true, msaa: true,
plugins: [PickingPlugin, FrameFadePlugin, SSAAPlugin],
plugins: [LoadingScreenPlugin, PickingPlugin, FrameFadePlugin, SSAAPlugin],
dropzone: { dropzone: {
addOptions: { addOptions: {
disposeSceneObjects: true, disposeSceneObjects: true,

+ 6
- 0
examples/switch-node-plugin/index.html 查看文件

margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
} }

#gridItemList{
/*because of the code preview button*/
top: 50px !important;
height: calc(100% - 50px) !important;
}
</style> </style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script> <script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>

+ 10
- 2
examples/switch-node-plugin/script.ts 查看文件

import {_testFinish, FrameFadePlugin, IObject3D, PickingPlugin, SSAAPlugin, ThreeViewer} from 'threepipe'
import {
_testFinish,
FrameFadePlugin,
IObject3D,
LoadingScreenPlugin,
PickingPlugin,
SSAAPlugin,
ThreeViewer,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'
import {SwitchNodePlugin} from '@threepipe/plugin-configurator' import {SwitchNodePlugin} from '@threepipe/plugin-configurator'


const viewer = new ThreeViewer({ const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement, canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true, msaa: true,
plugins: [PickingPlugin, FrameFadePlugin, SSAAPlugin],
plugins: [LoadingScreenPlugin, PickingPlugin, FrameFadePlugin, SSAAPlugin],
dropzone: { dropzone: {
addOptions: { addOptions: {
disposeSceneObjects: true, disposeSceneObjects: true,

+ 2
- 2
src/assetmanager/AssetManager.ts 查看文件

* State of download/upload/process/other processes in the viewer. * State of download/upload/process/other processes in the viewer.
* Subscribes to importer and exporter by default, more can be added by plugins like {@link FileTransferPlugin} * Subscribes to importer and exporter by default, more can be added by plugins like {@link FileTransferPlugin}
*/ */
processState: Map<string, {state: string, progress: number | undefined}> = new Map()
processState: Map<string, {state: string, progress?: number | undefined}> = new Map()


/** /**
* Set process state for a path * Set process state for a path
* @param path * @param path
* @param value * @param value
*/ */
setProcessState(path: string, value: {state: string, progress: number | undefined} | undefined) {
setProcessState(path: string, value: {state: string, progress?: number | undefined} | undefined) {
if (value === undefined) this.processState.delete(path) if (value === undefined) this.processState.delete(path)
else this.processState.set(path, value) else this.processState.set(path, value)
this.dispatchEvent({type: 'processStateUpdate'}) this.dispatchEvent({type: 'processStateUpdate'})

+ 4
- 4
src/assetmanager/MaterialManager.ts 查看文件

const oldMaps = this._materialMaps.get(mat.uuid) || new Set<ITexture>() const oldMaps = this._materialMaps.get(mat.uuid) || new Set<ITexture>()
for (const map of newMaps) { for (const map of newMaps) {
if (oldMaps.has(map)) continue if (oldMaps.has(map)) continue
if (!map.userData.__appliedMaterials) map.userData.__appliedMaterials = new Set<IMaterial>()
map.userData.__appliedMaterials.add(mat)
if (!map._appliedMaterials) map._appliedMaterials = new Set<IMaterial>()
map._appliedMaterials.add(mat)
map.addEventListener('update', mat.__textureUpdate) map.addEventListener('update', mat.__textureUpdate)
} }
for (const map of oldMaps) { for (const map of oldMaps) {
if (newMaps.has(map)) continue if (newMaps.has(map)) continue
map.removeEventListener('update', mat.__textureUpdate) map.removeEventListener('update', mat.__textureUpdate)
if (!map.userData.__appliedMaterials) continue
const mats = map.userData.__appliedMaterials
if (!map._appliedMaterials) continue
const mats = map._appliedMaterials
mats?.delete(mat) mats?.delete(mat)
if (!mats || map.userData.disposeOnIdle === false) continue if (!mats || map.userData.disposeOnIdle === false) continue
if (mats.size === 0) map.dispose() if (mats.size === 0) map.dispose()

+ 1
- 1
src/assetmanager/gltf/gltfEncyptionHelpers.ts 查看文件

* @param options * @param options
*/ */
export const glbEncryptionProcessor = async(gltf: ArrayBuffer|any, options: GLTFExporter2Options) => { export const glbEncryptionProcessor = async(gltf: ArrayBuffer|any, options: GLTFExporter2Options) => {
if (!gltf || typeof gltf === 'object' || !gltf.byteLength) return gltf
if (!gltf || !(gltf instanceof ArrayBuffer) || !gltf.byteLength || !options.encrypt) return gltf
if (!options.encryptKey && window && window.prompt) { if (!options.encryptKey && window && window.prompt) {
options.encryptKey = window.prompt('GLTFEncryption: Enter encryption key/password') || '' options.encryptKey = window.prompt('GLTFEncryption: Enter encryption key/password') || ''
} }

+ 3
- 2
src/core/ITexture.ts 查看文件

* Works only after it's applied to a material once. * Works only after it's applied to a material once.
*/ */
disposeOnIdle?: boolean disposeOnIdle?: boolean
__appliedMaterials?: Set<IMaterial>
} }
export type ITextureEventTypes = 'dispose' | 'update' export type ITextureEventTypes = 'dispose' | 'update'
export type ITextureEvent<T extends string = ITextureEventTypes> = Event & { export type ITextureEvent<T extends string = ITextureEventTypes> = Event & {
_sourceImgBuffer?: ArrayBuffer // see KTX2LoadPlugin and serializeTextureInExtras _sourceImgBuffer?: ArrayBuffer // see KTX2LoadPlugin and serializeTextureInExtras
} }


_appliedMaterials?: Set<IMaterial> // for internal use only. refers to the materials that this texture is applied to

_target?: IRenderTarget // for internal use only. refers to the render target that this texture is attached to _target?: IRenderTarget // for internal use only. refers to the render target that this texture is attached to
} }


export function upgradeTexture(this: ITexture) { export function upgradeTexture(this: ITexture) {
this.assetType = 'texture' this.assetType = 'texture'
if (!this.userData) this.userData = {} if (!this.userData) this.userData = {}
if (!this.userData.__appliedMaterials) this.userData.__appliedMaterials = new Set()
if (!this._appliedMaterials) this._appliedMaterials = new Set()
if (!this.setDirty) this.setDirty = ()=>this.needsUpdate = true if (!this.setDirty) this.setDirty = ()=>this.needsUpdate = true
// todo: uiconfig, dispose, etc // todo: uiconfig, dispose, etc
} }

+ 0
- 1
src/plugins/export/CanvasSnapshotPlugin.ts 查看文件

constructor() { constructor() {
super() super()
this.downloadSnapshot = this.downloadSnapshot.bind(this) this.downloadSnapshot = this.downloadSnapshot.bind(this)
this.getDataUrl({})
} }


/** /**

+ 14
- 8
src/plugins/extras/MeshOptSimplifyModifierPlugin.ts 查看文件

export class MeshOptSimplifyModifierPlugin extends SimplifyModifierPlugin { export class MeshOptSimplifyModifierPlugin extends SimplifyModifierPlugin {
public static readonly PluginType = 'MeshOptSimplifyModifierPlugin' public static readonly PluginType = 'MeshOptSimplifyModifierPlugin'


constructor(initialize = true) {
constructor(initialize = true, public readonly rootNode = document.head) {
super() super()
// todo: check if compatible? // todo: check if compatible?
if (initialize) this.initialize() if (initialize) this.initialize()
} }


protected _initializing?: Promise<void> = undefined protected _initializing?: Promise<void> = undefined
protected _script?: HTMLScriptElement


async initialize() { async initialize() {
if (this.initialized) return if (this.initialized) return
}); });
` `
this._initializing = new Promise<void>((res) => { this._initializing = new Promise<void>((res) => {
const l = () => {
window.removeEventListener(ev, l)
res() // todo timeout?
}
window.addEventListener(ev, l)
document.head.appendChild(s) // todo remove later?
// this._script = s
window.addEventListener(ev, ()=>res(), {once: true})
this.rootNode.appendChild(s)
this._script = s
}) })
return await this._initializing
}

dispose() {
if (this._script) {
this._script.remove()
delete window.MeshoptSimplifier
}
this._script = undefined
} }


@uiNumber() @uiNumber()

+ 17
- 8
src/plugins/import/KTX2LoadPlugin.ts 查看文件

import {KTX2Loader} from 'three/examples/jsm/loaders/KTX2Loader.js' import {KTX2Loader} from 'three/examples/jsm/loaders/KTX2Loader.js'
import {CompressedTexture} from 'three' import {CompressedTexture} from 'three'
import {serializeTextureInExtras} from '../../utils' import {serializeTextureInExtras} from '../../utils'
import {ITexture} from '../../core'
import {ITexture, upgradeTexture} from '../../core'
import {BaseImporterPlugin} from '../base/BaseImporterPlugin' import {BaseImporterPlugin} from '../base/BaseImporterPlugin'


/** /**
} }


export class KTX2Loader2 extends KTX2Loader implements ILoader { export class KTX2Loader2 extends KTX2Loader implements ILoader {
private _initTexture(t: CompressedTexture & ITexture) {
upgradeTexture.call(t)
t.userData.mimeType = 'image/ktx2'
t.toJSON = (meta?: any)=>{
return serializeTextureInExtras(t, meta, t.name, 'image/ktx2')
}
const cloneFn = t.clone
t.clone = ()=>{
const res = cloneFn.call(t)
if (res.source !== t.source) // in case something changes
res.source._sourceImgBuffer = t.source._sourceImgBuffer
return this._initTexture(res)
}
return t
}
async createTexture(buffer: ArrayBuffer, config: any): Promise<CompressedTexture> { async createTexture(buffer: ArrayBuffer, config: any): Promise<CompressedTexture> {
const buffer2 = new Uint8Array(buffer.slice(0)) // clones the buffer const buffer2 = new Uint8Array(buffer.slice(0)) // clones the buffer
const texture = (await super.createTexture(buffer, config)) as CompressedTexture & ITexture const texture = (await super.createTexture(buffer, config)) as CompressedTexture & ITexture
texture.source._sourceImgBuffer = buffer2 // keep the same buffer when cloned and all, used in serializeTextureInExtras texture.source._sourceImgBuffer = buffer2 // keep the same buffer when cloned and all, used in serializeTextureInExtras
texture.userData.mimeType = 'image/ktx2'
texture.toJSON = (meta?: any)=>{
return serializeTextureInExtras(texture, meta, texture.name, 'image/ktx2')
}
texture.clone = ()=>{
throw new Error('ktx2 texture cloning not supported')
}
this._initTexture(texture)
return texture return texture
} }



+ 3
- 3
src/three/utils/misc.ts 查看文件

/** /**
* Convert geometry to BufferGeometry with indexed attributes. * Convert geometry to BufferGeometry with indexed attributes.
*/ */
export function toIndexedGeometry(geometry: BufferGeometry<any, any, any>, tolerance = -1) {
return mergeVertices(geometry, tolerance)
export function toIndexedGeometry<T extends BufferGeometry<any, any, any> = BufferGeometry<any, any, any>>(geometry: T, tolerance = -1): T {
return mergeVertices(geometry, tolerance) as T
} }


export function generateUUID() { export function generateUUID() {
export function isInScene(...sceneObj: (IGeometry|IMaterial|IObject3D|ITexture)[]): boolean { export function isInScene(...sceneObj: (IGeometry|IMaterial|IObject3D|ITexture)[]): boolean {
if (sceneObj.length > 1) return sceneObj.some((a)=>isInScene(a)) if (sceneObj.length > 1) return sceneObj.some((a)=>isInScene(a))
const o = sceneObj[0] const o = sceneObj[0]
if ((<ITexture>o).isTexture) return Array.from((<ITexture>o).userData.__appliedMaterials || []).some((m) => isInScene(m)) ?? false
if ((<ITexture>o).isTexture) return Array.from((<ITexture>o)._appliedMaterials || []).some((m) => isInScene(m)) ?? false


const objects = const objects =
(<IObject3D>o).isObject3D ? [<IObject3D>o] : (<IObject3D>o).isObject3D ? [<IObject3D>o] :

Loading…
取消
儲存