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.
140 lines (138 loc) • 4.68 kB
JavaScript
import { EventDispatcher } from 'three';
import { ThreeSerialization } from '../utils';
/**
* Base Class for Viewer Plugins
* @category Viewer
*/
export class AViewerPlugin extends EventDispatcher {
constructor() {
super(...arguments);
this._dirty = false;
this.uiConfig = undefined; // if this is showing an error, remove all `get uiConfig` and use objects
this._viewerListeners = {};
this._onViewerEvent = (e) => {
const et = e.eType;
et && this._viewerListeners[et]?.(e);
return e;
};
this._disabledBy = new Set();
this.disable = (key, setDirty = true) => {
const size = this._disabledBy.size;
this._disabledBy.add(key);
if (setDirty && this.setDirty && size !== this._disabledBy.size)
this.setDirty();
};
this.enable = (key, setDirty = true) => {
const size = this._disabledBy.size;
this._disabledBy.delete(key);
if (setDirty && this.setDirty && size !== this._disabledBy.size)
this.setDirty();
};
this.isDisabled = () => {
return this._disabledBy.size > 0 || !this.enabled;
};
/**
* Template
toJSON(meta?: any): any {
const data = super.toJSON(meta)
if (!data.type) return data
// add here
return data
}
fromJSON(data: any, meta?: any): this | null {
if (!super.fromJSON(data, meta)) return null
// add here
return this
}
*/
}
dispose() {
return;
}
toJSON(meta) {
const data = ThreeSerialization.Serialize(this, meta, true);
data.type = this.constructor.PluginType;
data.assetType = 'config';
this.dispatchEvent({ type: 'serialize', data });
return data;
}
fromJSON(data, meta) {
if (data.type !== this.constructor.PluginType && data.type !== this.constructor.OldPluginType)
return null;
ThreeSerialization.Deserialize(data, this, meta, true);
this.dispatchEvent({ type: 'deserialize', data, meta });
return this;
}
_storeKey(prefix) {
return (prefix ?? 'webgi') + '_' + (this.constructor.PluginType || this.constructor.name);
}
exportState() {
return this._viewer?.exportPluginConfig(this) ?? this.toJSON?.();
}
async importState(state) {
if (this._viewer)
await this._viewer.importPluginConfig(state, this);
else
this.fromJSON?.(state);
}
// todo: move to ThreeViewer
// storeState(prefix?: string, storage?: Storage, data?: any): void {
// storage = storage || (window ? window.localStorage : undefined)
// if (!storage) {
// console.warn('Unable to store state')
// return
// }
// if (data === undefined) data = this.exportState()
// if (data) storage.setItem(this._storeKey(prefix), JSON.stringify(data))
// }
//
// async loadState(prefix?: string, storage?: Storage): Promise<void> {
// storage = storage || (window ? window.localStorage : undefined)
// if (!storage) {
// console.warn('Unable to load state')
// return
// }
// const data = storage.getItem(this._storeKey(prefix))
// if (data) await this.importState(JSON.parse(data))
// }
get dirty() {
return this.enabled && this._dirty;
}
set dirty(value) {
this._dirty = value;
}
}
AViewerPlugin.PluginType = 'AViewerPlugin';
/**
* Base Class for Sync Viewer Plugins
* @category Viewer
*/
export class AViewerPluginSync extends AViewerPlugin {
onAdded(viewer) {
this._viewer = viewer;
this._viewer.addEventListener('*', this._onViewerEvent);
}
onRemove(viewer) {
if (this._viewer !== viewer)
viewer.console.error('Wrong viewer');
this._viewer?.removeEventListener('*', this._onViewerEvent);
this._viewer = undefined;
}
}
/**
* Base Class for Async Viewer Plugins
* @category Viewer
*/
export class AViewerPluginAsync extends AViewerPlugin {
async onAdded(viewer) {
this._viewer = viewer;
this._viewer.addEventListener('*', this._onViewerEvent);
}
async onRemove(viewer) {
if (this._viewer !== viewer)
viewer.console.error('Wrong viewer');
this._viewer?.removeEventListener('*', this._onViewerEvent);
this._viewer = undefined;
}
}
//# sourceMappingURL=AViewerPlugin.js.map