replay-viewer
Version:
Rocket League replay viewer React component and tooling
188 lines • 8.57 kB
JavaScript
import { OrthographicCamera, PerspectiveCamera, Vector3 } from "three";
import { ABOVE_FIELD_CAMERA, BLUE_GOAL_CAMERA, FREE_CAMERA, ORANGE_GOAL_CAMERA, ORTHOGRAPHIC, } from "../constants/gameObjectNames";
import { dispatchCameraChange } from "../eventbus/events/cameraChange";
import { dispatchCameraFrameUpdate } from "../eventbus/events/cameraFrameUpdate";
import { addCanvasResizeListener, removeCanvasResizeListener, } from "../eventbus/events/canvasResize";
import { addFrameListener, removeFrameListener } from "../eventbus/events/frame";
import { addKeyControlListener, applyDirections, removeKeyControlListener, } from "../eventbus/events/keyControl";
import { isOrthographicCamera } from "../operators/isOrthographicCamera";
import SceneManager from "./SceneManager";
var CameraManager = /** @class */ (function () {
function CameraManager() {
var _this = this;
this.updateSize = function (_a) {
var width = _a.width, height = _a.height;
_this.width = width;
_this.height = height;
_this.updateCameraSize();
};
this.update = function () {
var position = SceneManager.getInstance().ball.ball.position;
dispatchCameraFrameUpdate({
ballPosition: position,
ballCam: _this.ballCam,
isUsingBoost: false,
activeCamera: _this.activeCamera
});
if (!isOrthographicCamera(_this.activeCamera)) {
_this.activeCamera.lookAt(position);
}
};
this.onKeyControl = function (_a) {
var directions = _a.directions, speed = _a.speed;
if (_this.activeCamera.name === FREE_CAMERA) {
var cameraDirection = new Vector3();
_this.activeCamera.getWorldDirection(cameraDirection);
var multiplier = speed ? 75 : 15;
var newDirection = applyDirections(cameraDirection, directions, multiplier);
var newPosition = new Vector3();
newPosition.copy(_this.activeCamera.position);
newPosition.add(newDirection);
// Don't allow phasing inside of the ball
var ballPosition = SceneManager.getInstance().ball.ball.position;
if (ballPosition.distanceTo(newPosition) < 200) {
return;
}
// Don't allow cameras under the field
if (newPosition.y < 10) {
newPosition.setY(10);
}
// If all checks pass, set the new position
_this.activeCamera.position.copy(newPosition);
_this.update();
dispatchCameraChange({ camera: _this.activeCamera });
}
};
this.activeCamera = SceneManager.getInstance().field.getCamera(ORANGE_GOAL_CAMERA);
this.defaultCamera = this.activeCamera;
this.width = 640;
this.height = 480;
this.ballCam = true;
this.activeCamera.position.z = 5000;
this.activeCamera.position.y = 750;
addFrameListener(this.update);
addCanvasResizeListener(this.updateSize);
addKeyControlListener(this.onKeyControl);
}
CameraManager.prototype.toggleBallCam = function () {
this.ballCam = !this.ballCam;
this.update();
};
CameraManager.prototype.setCameraLocation = function (_a) {
var playerName = _a.playerName, fieldLocation = _a.fieldLocation;
var _b = SceneManager.getInstance(), players = _b.players, field = _b.field;
if (playerName) {
var player = players.find(function (p) { return p.playerName === playerName; });
if (player) {
this.setActiveCamera(player.camera);
}
}
else if (fieldLocation) {
switch (fieldLocation) {
case "orange":
this.setActiveCamera(field.getCamera(ORANGE_GOAL_CAMERA));
break;
case "blue":
this.setActiveCamera(field.getCamera(BLUE_GOAL_CAMERA));
break;
case "center":
this.setActiveCamera(field.getCamera(ABOVE_FIELD_CAMERA));
break;
case "freecam":
var freecam = field.getCamera(FREE_CAMERA);
if (!isOrthographicCamera(this.activeCamera)) {
if (freecam.parent) {
freecam.parent.updateMatrixWorld();
}
freecam.position.setFromMatrixPosition(this.activeCamera.matrixWorld);
freecam.rotation.fromArray(this.activeCamera.rotation.toArray());
}
this.setActiveCamera(freecam);
break;
case "orthographic-above-field":
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.ABOVE_FIELD));
break;
case "orthographic-orange-left":
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.ORANGE_LEFT));
break;
case "orthographic-orange-right":
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.ORANGE_RIGHT));
break;
case "orthographic-blue-left":
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.BLUE_LEFT));
break;
case "orthographic-blue-right":
this.setActiveCamera(field.getCamera(ORTHOGRAPHIC.BLUE_RIGHT));
break;
default:
this.setActiveCamera(this.defaultCamera);
}
}
// Dispatch to all manager listeners
dispatchCameraChange({ camera: this.activeCamera });
};
CameraManager.prototype.updateCameraSize = function () {
var _a = this, camera = _a.activeCamera, width = _a.width, height = _a.height;
if (camera instanceof PerspectiveCamera) {
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
else if (camera instanceof OrthographicCamera) {
/**
* Here, we are computing the zoom of the camera given the aspect ratio. For cameras with an
* aspect ratio greater than 4:3, we base the zoom on the height. Otherwise, we use width. The
* minimum zoom should always be 0.02.
*
* The zoom when based on the height is a simple linear function y = x / 12500 + 0.01, where x
* is the new height and y is the desired zoom.
*
* The denominator of the width-based computation is simply the slope of the previous
* function, 12500, multiplied by 1.3 since this is aspect ratio breaking point we have set in
* the if statement.
*/
if (width / height > 1.3) {
var newZoom = height / 12500 + 0.01;
camera.zoom = Math.max(newZoom, 0.02);
}
else {
var newZoom = width / 16250 + 0.01;
camera.zoom = Math.max(newZoom, 0.02);
}
camera.left = -width / 2;
camera.right = width / 2;
camera.top = height / 2;
camera.bottom = -height / 2;
camera.updateProjectionMatrix();
}
};
CameraManager.prototype.setActiveCamera = function (camera) {
if (!camera) {
return;
}
this.activeCamera = camera;
this.updateCameraSize();
this.update();
};
CameraManager.getInstance = function () {
if (!CameraManager.instance) {
throw new Error("CameraManager not initialized with call to `init`");
}
return CameraManager.instance;
};
CameraManager.init = function () {
CameraManager.instance = new CameraManager();
return CameraManager.instance;
};
CameraManager.destruct = function () {
var instance = CameraManager.instance;
if (instance) {
removeFrameListener(instance.update);
removeCanvasResizeListener(instance.updateSize);
removeKeyControlListener(instance.onKeyControl);
CameraManager.instance = undefined;
}
};
return CameraManager;
}());
export default CameraManager;
//# sourceMappingURL=CameraManager.js.map