@deck.gl/core
Version:
deck.gl core library
107 lines (92 loc) • 3.16 kB
text/typescript
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import Transition from './transition';
import {cloneAttribute, getAttributeBufferLength} from './gpu-transition-utils';
import type {Device, Buffer} from '@luma.gl/core';
import type {Timeline} from '@luma.gl/engine';
import type Attribute from '../lib/attribute/attribute';
import type {TransitionSettings} from '../lib/attribute/transition-settings';
import type {NumericArray} from '../types/types';
export interface GPUTransition {
get type(): string;
get inProgress(): boolean;
get attributeInTransition(): Attribute;
/** Called when an attribute's values have changed and we need to start animating towards the new values */
start(transitionSettings: TransitionSettings, numInstances: number): void;
/** Called while transition is in progress */
update(): boolean;
/** Called when transition is interrupted */
cancel(): void;
/** Called when transition is disposed */
delete(): void;
}
export abstract class GPUTransitionBase<SettingsT extends TransitionSettings>
implements GPUTransition
{
abstract get type(): string;
device: Device;
attribute: Attribute;
transition: Transition;
settings?: SettingsT;
/** The attribute that holds the buffer in transition */
attributeInTransition: Attribute;
protected buffers: Buffer[] = [];
/** The vertex count of the last buffer.
* Buffer may be larger than the actual length we want to use
* because we only reallocate buffers when they grow, not when they shrink,
* due to performance costs */
protected currentLength: number = 0;
/** The start indices of the last buffer. */
protected currentStartIndices: NumericArray | null;
constructor({
device,
attribute,
timeline
}: {
device: Device;
attribute: Attribute;
timeline: Timeline;
}) {
this.device = device;
this.transition = new Transition(timeline);
this.attribute = attribute;
this.attributeInTransition = cloneAttribute(attribute);
this.currentStartIndices = attribute.startIndices;
}
get inProgress(): boolean {
return this.transition.inProgress;
}
start(transitionSettings: SettingsT, numInstances: number, duration: number = Infinity) {
this.settings = transitionSettings;
this.currentStartIndices = this.attribute.startIndices;
this.currentLength = getAttributeBufferLength(this.attribute, numInstances);
this.transition.start({...transitionSettings, duration});
}
update(): boolean {
const updated = this.transition.update();
if (updated) {
this.onUpdate();
}
return updated;
}
abstract onUpdate(): void;
protected setBuffer(buffer: Buffer) {
this.attributeInTransition.setData({
buffer,
normalized: this.attribute.settings.normalized,
// Retain placeholder value to generate correct shader layout
value: this.attributeInTransition.value as NumericArray
});
}
cancel(): void {
this.transition.cancel();
}
delete(): void {
this.cancel();
for (const buffer of this.buffers) {
buffer.destroy();
}
this.buffers.length = 0;
}
}