threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
205 lines • 7.53 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
// noinspection ES6PreferShortImport
import { AViewerPluginSync } from '../../viewer/AViewerPlugin';
import { Dropzone } from '../../utils';
import { uiButton, uiConfig, uiFolderContainer, uiToggle } from 'uiconfig.js';
import { parseFileExtension, serialize } from 'ts-browser-helpers';
/**
* Dropzone Plugin
*
* Adds a dropzone to the viewer for importing assets.
*
* Automatically imports and adds assets to the scene, the behavior can be configured.
* @category Plugins
*/
let DropzonePlugin = class DropzonePlugin extends AViewerPluginSync {
/**
* Allowed file extensions. If undefined, all files are allowed.
*/
get allowedExtensions() {
return this._allowedExtensions;
}
set allowedExtensions(value) {
this._allowedExtensions = value;
if (this._inputEl)
this._inputEl.accept = value ? value.map(v => '.' + v).join(', ') : '';
}
/**
* Prompt for file selection using the browser file dialog.
*/
promptForFile() {
if (this.isDisabled())
return;
this.allowedExtensions = this._allowedExtensions;
this._inputEl?.click();
}
/**
* Prompt for file url.
*/
async promptForUrl() {
if (this.isDisabled() || !this._viewer)
return;
const res = await this._viewer.dialog.prompt('Enter URL: Enter a public URL for a 3d file with extension', '', true);
if (!res || !res.length)
return;
await this.load(res, {}, true);
}
async load(res, options, dialog = false) {
if (!this._viewer) {
console.warn('DropzonePlugin: viewer not set');
return;
}
if (this.autoImport) {
const manager = this._viewer.assetManager;
const ext = parseFileExtension(res);
if (this._allowedExtensions && !this._allowedExtensions.includes(ext)) {
dialog && await this._viewer.dialog.alert(`DropzonePlugin: file extension ${ext} not allowed`);
return;
}
const imported = await manager.importer.import(res, {
...this.importOptions,
...options ?? {},
});
const toAdd = [...imported ?? []].flat(2).filter(v => !!v) ?? [];
if (this.autoAdd) {
return await manager.loadImported(toAdd, {
...this.addOptions,
...options ?? {},
});
}
return toAdd;
}
else {
dialog && await this._viewer.dialog.alert('DropzonePlugin: autoImport is disabled, file was not imported');
}
}
constructor(options) {
super();
this.enabled = true;
this._allowedExtensions = undefined; // undefined and empty array is different.
/**
* Automatically import assets when dropped.
*/
this.autoImport = true;
/**
* Automatically add dropped and imported assets to the scene.
* Works only if {@link autoImport} is true.
*/
this.autoAdd = true;
/**
* Import options for the {@link AssetImporter.importFiles}
*/
this.importOptions = {
autoImportZipContents: true,
forceImporterReprocess: false,
};
/**
* Add options for the {@link RootScene.addObject}
*/
this.addOptions = {
autoCenter: true,
importConfig: true,
autoScale: true,
autoScaleRadius: 2,
centerGeometries: false, // in the whole hierarchy
centerGeometriesKeepPosition: true, // this centers while keeping world position
license: '',
clearSceneObjects: false,
disposeSceneObjects: false,
autoSetBackground: false,
autoSetEnvironment: true,
};
if (!options)
return;
this._domElement = options.domElement;
this.allowedExtensions = options.allowedExtensions;
this.autoImport = options.autoImport ?? this.autoImport;
this.autoAdd = options.autoAdd ?? this.autoAdd;
this.importOptions = { ...this.importOptions, ...options.importOptions };
this.addOptions = { ...this.addOptions, ...options.addOptions };
}
onAdded(viewer) {
super.onAdded(viewer);
this._inputEl = document.createElement('input');
this._inputEl.type = 'file';
if (!this._domElement)
this._domElement = viewer.canvas;
this._dropzone = new Dropzone(this._domElement, this._inputEl, {
drop: this._onFileDrop.bind(this),
});
this.allowedExtensions = this._allowedExtensions;
}
onRemove(viewer) {
super.onRemove(viewer);
this._dropzone?.destroy();
this._dropzone = undefined;
this._inputEl = undefined;
}
async _onFileDrop({ files, nativeEvent }) {
if (!files)
return;
if (this.isDisabled())
return;
const viewer = this._viewer;
if (!viewer)
return;
if (this._allowedExtensions !== undefined) {
for (const file of files.keys()) {
if (!this._allowedExtensions.includes(file.split('.').pop()?.toLowerCase() ?? '')) {
files.delete(file);
}
}
}
if (files.size < 1)
return;
const manager = viewer.assetManager;
let imported;
let assets;
if (this.autoImport) {
imported = await manager.importer.importFiles(files, {
allowedExtensions: this.allowedExtensions, ...this.importOptions,
});
if (this.autoAdd) {
const toAdd = [...imported?.values() ?? []].flat(2).filter(v => !!v) ?? [];
assets = await manager.loadImported(toAdd, { ...this.addOptions });
}
}
this.dispatchEvent({ type: 'drop', files, imported, assets, nativeEvent });
}
};
DropzonePlugin.PluginType = 'Dropzone';
__decorate([
uiToggle(),
serialize()
], DropzonePlugin.prototype, "enabled", void 0);
__decorate([
serialize()
], DropzonePlugin.prototype, "autoImport", void 0);
__decorate([
uiToggle(),
serialize()
], DropzonePlugin.prototype, "autoAdd", void 0);
__decorate([
uiConfig(),
serialize()
], DropzonePlugin.prototype, "importOptions", void 0);
__decorate([
uiConfig(),
serialize()
], DropzonePlugin.prototype, "addOptions", void 0);
__decorate([
uiButton('Select Local files')
], DropzonePlugin.prototype, "promptForFile", null);
__decorate([
uiButton('Import from URL')
], DropzonePlugin.prototype, "promptForUrl", null);
DropzonePlugin = __decorate([
uiFolderContainer('Dropzone')
], DropzonePlugin);
export { DropzonePlugin };
//# sourceMappingURL=DropzonePlugin.js.map