UNPKG

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.

178 lines 8.23 kB
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; }; var TransformControlsPlugin_1; import { uiButton, uiConfig, uiPanelContainer, uiToggle } from 'uiconfig.js'; import { AViewerPluginSync } from '../../viewer'; import { TransformControls2 } from '../../three'; import { PickingPlugin } from './PickingPlugin'; import { onChange } from 'ts-browser-helpers'; import { TransformControls } from '../../three/controls/TransformControls'; import { UnlitLineMaterial, UnlitMaterial } from '../../core'; import { Euler, Vector3 } from 'three'; let TransformControlsPlugin = TransformControlsPlugin_1 = class TransformControlsPlugin extends AViewerPluginSync { setDirty() { if (!this._viewer) return; const picking = this._viewer.getPlugin(PickingPlugin); const enabled = !this.isDisabled(); if (enabled && picking.widgetEnabled) { picking.widgetEnabled = false; this._pickingWidgetDisabled = true; } else if (!enabled && this._pickingWidgetDisabled) { picking.widgetEnabled = true; this._pickingWidgetDisabled = false; } if (this.transformControls) { if (enabled && picking.getSelectedObject()?.isObject3D) this.transformControls.attach(picking.getSelectedObject()); else this.transformControls.detach(); } this._viewer.setDirty(); } constructor(enabled = true) { super(); this.enabled = true; this._pickingWidgetDisabled = false; this.toJSON = undefined; this.dependencies = [PickingPlugin]; this._isInteracting = false; this._viewerListeners = { postFrame: () => { if (!this.transformControls || !this._viewer) return; // this._viewer.scene.mainCamera.setInteractions(!this._isInteracting, TransformControlsPlugin.PluginType) }, }; this._transformState = { obj: null, position: new Vector3(), rotation: new Euler(), scale: new Vector3(), }; this._mainCameraChange = () => { if (!this.transformControls || !this._viewer) return; this.transformControls.camera = this._viewer.scene.mainCamera; }; TransformControls.ObjectConstructors.MeshBasicMaterial = UnlitMaterial; TransformControls.ObjectConstructors.LineBasicMaterial = UnlitLineMaterial; this.enabled = enabled; } onAdded(viewer) { super.onAdded(viewer); this.setDirty(); this.transformControls = new TransformControls2(viewer.scene.mainCamera, viewer.canvas); this._mainCameraChange = this._mainCameraChange.bind(this); viewer.scene.addEventListener('mainCameraChange', this._mainCameraChange); this.transformControls.addEventListener('dragging-changed', (event) => { if (!this?._viewer) return; const controls = this._viewer.scene.mainCamera.controls; if (typeof controls?.stopDamping === 'function' && controls?.enabled) controls.stopDamping(); this._viewer.scene.mainCamera.setInteractions(!event.value, TransformControlsPlugin_1.PluginType); // this._viewer.scene.mainCamera.autoNearFar = !event.value // todo: maintain state }); this.transformControls.addEventListener('axis-changed', (event) => { if (!this?._viewer) return; this._isInteracting = !!event.value; const controls = this._viewer.scene.mainCamera.controls; if (typeof controls?.stopDamping === 'function' && controls?.enabled) controls.stopDamping(); this._viewer.setDirty(); // rerender for color change }); viewer.scene.addObject(this.transformControls, { addToRoot: true }); const picking = viewer.getPlugin(PickingPlugin); picking.addEventListener('selectedObjectChanged', (event) => { if (!this.transformControls) return; if (this.isDisabled()) { if (this.transformControls.object) this.transformControls.detach(); return; } event.object ? this.transformControls.attach(event.object) : this.transformControls.detach(); }); viewer.forPlugin('UndoManagerPlugin', (um) => { this.undoManager = um.undoManager; }, () => this.undoManager = undefined); // same logic for undo as three.js editor. todo It can be made better by syncing with the UI so it supports the hotkeys and other properties inside TransformControls2 this.transformControls.addEventListener('mouseDown', () => { if (!this.transformControls) return; const object = this.transformControls.object; if (!object) return; this._transformState.obj = object; this._transformState.position = object.position.clone(); this._transformState.rotation = object.rotation.clone(); this._transformState.scale = object.scale.clone(); }); this.transformControls.addEventListener('mouseUp', () => { if (!this.transformControls) return; const object = this.transformControls.object; if (!object) return; if (this._transformState.obj !== object || !this.undoManager) return; const key = { 'translate': 'position', 'rotate': 'rotation', 'scale': 'scale', }[this.transformControls.getMode()]; if (!key) return; if (this._transformState[key].equals(object[key])) return; const command = { last: this._transformState[key].clone(), current: object[key].clone(), set: (value) => { object[key].copy(value); object.updateMatrixWorld(true); this.transformControls?.dispatchEvent({ type: 'change' }); this.transformControls?.dispatchEvent({ type: 'objectChange' }); }, undo: () => command.set(command.last), redo: () => command.set(command.current), }; this.undoManager.record(command); }); } onRemove(viewer) { viewer.scene.removeEventListener('mainCameraChange', this._mainCameraChange); if (this.transformControls) { this.transformControls.detach(); viewer.scene.remove(this.transformControls); this.transformControls.dispose(); } this.transformControls = undefined; super.onRemove(viewer); } centerAllMeshes() { return this._viewer?.scene.centerAllGeometries(true); } }; TransformControlsPlugin.PluginType = 'TransformControlsPlugin'; __decorate([ uiToggle(), onChange(TransformControlsPlugin.prototype.setDirty) ], TransformControlsPlugin.prototype, "enabled", void 0); __decorate([ uiConfig(undefined, { expanded: true }) ], TransformControlsPlugin.prototype, "transformControls", void 0); __decorate([ uiButton('Center All Meshes') ], TransformControlsPlugin.prototype, "centerAllMeshes", null); TransformControlsPlugin = TransformControlsPlugin_1 = __decorate([ uiPanelContainer('Transform Controls') ], TransformControlsPlugin); export { TransformControlsPlugin }; //# sourceMappingURL=TransformControlsPlugin.js.map