replay-viewer
Version:
Rocket League replay viewer React component and tooling
147 lines • 5.29 kB
JavaScript
import { dispatchFrameEvent } from "../eventbus/events/frame";
/**
* This clock provides a simple callback system that keeps track of elapsed and delta time
* transformations. This makes it extremely easy to parse the deltas of a replay by their frame
* count, and maintain a real-time comparison against those frames. Primarily to be used by the
* THREE.js animation system and communicate changes back to the parent container of animations so
* that we can display data which is recorded at a frame and not at a time.
*
* When constructing this object, you should provide an array of elapsed durations*1000, where each
* index in the array represents the time in milliseconds since the beginning of the animation. The
* first index, 0, should be set to 0 (the elapsed time since the start), followed by these times.
*
* For example:
* 0: 0
* 1: 483.877919614315
* 2: 838.5848999023438
* 3: 1322.4628567695618
* 4: 1809.6305429935455
*/
var FPSClock = /** @class */ (function () {
function FPSClock(frameToDuration) {
this.frameToDuration = frameToDuration;
this.paused = true;
this.deltaQueue = [];
this.elapsedTime = 0;
this.currentFrame = 0;
this.lastDelta = 0;
this.update = this.update.bind(this);
this.timeout();
}
FPSClock.prototype.reset = function () {
this.setFrame(0);
};
FPSClock.prototype.setFrame = function (frame) {
// Prevent negative frames
frame = frame < 0 ? 0 : frame;
var diff = this.frameToDuration[frame] - this.frameToDuration[this.currentFrame];
this.deltaQueue.push(diff);
this.currentFrame = frame;
this.doCallbacks();
};
FPSClock.prototype.isPaused = function () {
return this.paused;
};
FPSClock.prototype.play = function () {
if (this.paused) {
this.lastDelta = performance.now();
this.paused = false;
this.timeout();
}
};
FPSClock.prototype.pause = function () {
this.paused = true;
this.doCallbacks();
this.timeout(false);
};
/**
* Returns the elapsed time in milliseconds.
*/
FPSClock.prototype.getElapsedTime = function () {
return this.frameToDuration[this.currentFrame];
};
/**
* Returns the number of seconds elapsed since the last time getDelta was called. This function
* uses a combination of the performance.now() functionality when animations are rolling,
* combined with a small queue of delta modifications made by the setFrame function. This will
* allow us to apply delta factors quite easily and in one spot (i.e. 2x speed) as opposed to
* scattering arithmetic throughout the code.
*
* @returns {number} seconds
*/
FPSClock.prototype.getDelta = function () {
var now = performance.now();
// Initialize empty delta
if (!this.lastDelta) {
this.lastDelta = now;
}
// Only apply "now" when not paused
if (!this.paused) {
this.deltaQueue.push(now - this.lastDelta);
}
this.lastDelta = now;
// Process every delta contributer
var delta = 0;
while (this.deltaQueue.length) {
var time = this.deltaQueue.pop();
if (time) {
delta += time;
}
}
// Use the elapsed deltas for bookkeeping
this.elapsedTime += delta;
return delta / 1000;
};
FPSClock.prototype.update = function () {
if (!this.paused) {
this.getElapsedFrames();
this.doCallbacks();
}
};
FPSClock.prototype.getElapsedFrames = function () {
if (this.currentFrame >= this.frameToDuration.length - 1) {
this.pause();
}
if (this.frameToDuration[this.currentFrame] >= this.elapsedTime) {
this.currentFrame = 0;
}
while (this.frameToDuration[this.currentFrame + 1] < this.elapsedTime) {
this.currentFrame += 1;
}
};
FPSClock.prototype.timeout = function (enable) {
if (enable === void 0) { enable = true; }
if (enable) {
this.animation = setInterval(this.update, 1000 / 60);
}
else if (this.animation) {
clearInterval(this.animation);
}
};
FPSClock.prototype.doCallbacks = function () {
dispatchFrameEvent({
delta: this.getDelta(),
frame: this.currentFrame,
elapsedTime: this.getElapsedTime(),
});
};
/**
* Note that the final frame is ignored when considering the elapsed time per frame. If we
* considered this final delta, we would need a frame to "animate to".
*
* @param data Contains frame delta information
*/
FPSClock.convertReplayToClock = function (data) {
var elapsedTime = 0;
var frames = data.frames.map(function (frameInfo) {
var retValue = elapsedTime;
var delta = frameInfo[0] * 1000;
elapsedTime += delta;
return retValue;
});
return new FPSClock(frames);
};
return FPSClock;
}());
export default FPSClock;
//# sourceMappingURL=FPSClock.js.map