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.

211 lines 7.29 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; }; import { Clock, EventDispatcher } from 'three'; import { uiButton, uiFolderContainer, uiInput, uiToggle } from 'uiconfig.js'; import { onChangeDispatchEvent, serializable, serialize } from 'ts-browser-helpers'; let ViewerTimeline = class ViewerTimeline extends EventDispatcher { constructor() { super(...arguments); this._time = 0; /** * in secs */ this.delta = 0; /** * Maximum time in secs. * This is used to limit the time in the timeline. * Set to 0 to disable the limit. */ this.endTime = 2; /** * Reset the timeline time to 0 when the timeline ends. * It is applicable only when the timeline is running and `endTime` is set to a value greater than 0. * This can be used to loop the timeline. * @default true */ this.resetOnEnd = true; /** * Stop the timeline when it reaches the end. * This is applicable only when the timeline is running and `endTime` is set to a value greater than 0. * This can be used to stop the timeline when it reaches the end. * It is separate from `resetOnEnd`, the timeline is stopped and then reset when both are true. * @default false */ this.stopOnEnd = false; /** * Running state. */ this.running = false; this._clock = new Clock(false); this._start = false; this._stop = false; this._reset = false; // this is seek, not step actually this._step = false; } /** * Current time in secs */ get time() { return this._time; } /** * Set the current time and step a frame * @param value */ set time(value) { if (this._time === value) return; this.setTime(value, true); } /** * Returns true if the timeline is running or if it is set to step this/next frame. */ shouldRun() { return this.running || this._step; } start() { this._start = true; // start next frame if (this._stop) this._stop = false; if (this._step) this._step = false; } stop() { this._stop = true; // stop next frame if (this._start) this._start = false; if (this._step) this._step = false; } // @uiButton('Step') // step() { // if ((this.running || this._start) && !this._stop) return // this._step = true // stop next frame // } reset() { this._reset = true; // reset next frame if (this._step) this._step = false; // dont step if called before reset // if (this._start) this._start = false // if (this._stop) this._stop = false } update(viewer) { this._refreshParams(); if (!this.running) { this.delta = this._clock.getDelta(); // this will return 0 always this.time = this._clock.elapsedTime; return; } const d = viewer.getPlugin('ProgressivePlugin')?.postFrameConvergedRecordingDelta(); if (d && d > 0) { // recorded frame this.delta = d / 1000; this._clock.oldTime += d; this._clock.elapsedTime += this.delta; this.time = this._clock.elapsedTime; // viewer.setDirty(this) // for next frame this.dispatchEvent({ type: 'update' }); } else if (d !== undefined && d === 0) { // recording, not converged yet. this.delta = 0; this.time = this._clock.elapsedTime; } else if (d === undefined || d < 0) { // not recording this.delta = this._clock.getDelta(); // this updates oldTime and elapsedTime this.time = this._clock.elapsedTime; // viewer.setDirty(this) // for next frame this.dispatchEvent({ type: 'update' }); } this._refreshParams(); } _refreshParams() { const isEnd = this.endTime > 0 && this.time >= this.endTime && this.running; const isReset = this.resetOnEnd && isEnd; const isStop = this.stopOnEnd && isEnd; if (this._stop || isStop) { this._clock.stop(); this._start = false; this._stop = false; this.running = this._clock.running; this.dispatchEvent({ type: 'stop' }); } if (this._start) { this._clock.start(); this._clock.elapsedTime = this.time; this._start = false; this.running = this._clock.running; this.dispatchEvent({ type: 'start' }); } if (this._reset || isReset) { this._clock.elapsedTime = 0; this.time = 0; this.delta = 0; this._reset = false; this.dispatchEvent({ type: 'reset' }); } this.running = this._clock.running; } // todo better name update2(_viewer) { this._step = false; } setTime(t, stepFrame = true) { if (t < 0) t = 0; this._clock.elapsedTime = t; this._time = t; this.delta = 0; // reset delta // this._start = false // this._stop = false this._reset = false; if (!this._start) this._step = stepFrame; this.dispatchEvent({ type: 'update' }); } }; __decorate([ uiInput('Time', { readOnly: true }) ], ViewerTimeline.prototype, "time", null); __decorate([ uiInput('Delta', { readOnly: true }) ], ViewerTimeline.prototype, "delta", void 0); __decorate([ uiInput('Max Time'), serialize(), onChangeDispatchEvent('endTimeChanged') ], ViewerTimeline.prototype, "endTime", void 0); __decorate([ uiToggle('Reset on End'), serialize(), onChangeDispatchEvent('resetOnEndChanged') ], ViewerTimeline.prototype, "resetOnEnd", void 0); __decorate([ uiToggle('Stop on End'), serialize(), onChangeDispatchEvent('stopOnEndChanged') ], ViewerTimeline.prototype, "stopOnEnd", void 0); __decorate([ uiInput('Running', { readOnly: true }) ], ViewerTimeline.prototype, "running", void 0); __decorate([ uiButton('Start') ], ViewerTimeline.prototype, "start", null); __decorate([ uiButton('Stop') ], ViewerTimeline.prototype, "stop", null); __decorate([ uiButton('Reset') ], ViewerTimeline.prototype, "reset", null); ViewerTimeline = __decorate([ serializable('ViewerTimeline'), uiFolderContainer('Timeline') ], ViewerTimeline); export { ViewerTimeline }; //# sourceMappingURL=ViewerTimeline.js.map