mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
134 lines • 6.04 kB
JavaScript
import { Object3D, PerspectiveCamera } from "three";
import scene from "../../../engine/scene";
import { onBeforeRender } from "../../../events/onBeforeRender";
import { characterCameraDefaults, characterCameraSchema } from "../../../interface/ICharacterCamera";
import { getSelectionTarget } from "../../../states/useSelectionTarget";
import { getTransformControlsDragging } from "../../../states/useTransformControlsDragging";
import OrbitCameraBase from "../OrbitCameraBase";
import { euler, quaternion } from "../../utils/reusables";
import { getLoadedObject } from "../Loaded";
import getWorldQuaternion from "../../utils/getWorldQuaternion";
import { getEditorModeComputed } from "../../../states/useEditorModeComputed";
import characterCameraPlaced from "./characterCameraPlaced";
import { FAR, NEAR } from "../../../globals";
import { getCentripetal } from "../../../states/useCentripetal";
import applyCentripetalQuaternion from "../../utils/applyCentripetalQuaternion";
import fpsAlpha from "../../utils/fpsAlpha";
export default class CharacterCamera extends OrbitCameraBase {
static defaults = characterCameraDefaults;
static schema = characterCameraSchema;
constructor() {
super(new PerspectiveCamera(75, 1, NEAR, FAR));
const midObject3d = (this.midObject3d = new Object3D());
this.outerObject3d.add(midObject3d);
midObject3d.add(this.object3d);
const cam = this.camera;
scene.attach(cam);
this.then(() => scene.remove(cam));
this.createEffect(() => {
const target = this.targetState.get();
if (!target)
return;
if ("frustumCulled" in target)
target.frustumCulled = false;
}, [this.targetState.get]);
const followTargetRotation = (target, slerp) => {
euler.setFromQuaternion(target.outerObject3d.quaternion);
euler.y += Math.PI;
if (slerp) {
quaternion.setFromEuler(euler);
midObject3d.quaternion.slerp(quaternion, fpsAlpha(0.1));
}
else
midObject3d.setRotationFromEuler(euler);
this.updateAngle();
};
const lockTargetRotation = (target, slerp, quat) => {
euler.setFromQuaternion(this.midObject3d.quaternion);
euler.x = 0;
euler.z = 0;
euler.y += Math.PI;
if (quat) {
const innerObject = getLoadedObject(target);
quaternion.copy(target.outerObject3d.quaternion);
const innerRotationY = innerObject.rotation.y;
target.outerObject3d.quaternion.copy(quat);
innerObject.rotation.y = euler.y;
euler.setFromQuaternion(getWorldQuaternion(innerObject));
innerObject.rotation.y = innerRotationY;
target.outerObject3d.quaternion.copy(quaternion);
}
const placed = characterCameraPlaced.has(target);
if (slerp && !placed) {
quaternion.setFromEuler(euler);
target.outerObject3d.quaternion.slerp(quaternion, fpsAlpha(0.1));
return;
}
target.outerObject3d.setRotationFromEuler(euler);
quat && placed && characterCameraPlaced.delete(target);
};
let transformControlRotating = false;
this.createEffect(() => {
const target = this.targetState.get();
if (!target)
return;
followTargetRotation(target, false);
let [xOld, yOld, zOld] = [0, 0, 0];
const targetMoved = () => {
const { x, y, z } = target.outerObject3d.position;
const result = x !== xOld || y !== yOld || z !== zOld;
[xOld, yOld, zOld] = [x, y, z];
return result;
};
const centripetal = getCentripetal();
const handle = onBeforeRender(() => {
this.outerObject3d.position.copy(target.outerObject3d.position);
const quat = centripetal
? applyCentripetalQuaternion(this)
: undefined;
if (!this.lockTargetRotation)
return;
if (this.lockTargetRotation === "follow" ||
transformControlRotating) {
followTargetRotation(target, false);
return;
}
if (this.lockTargetRotation === "dynamic-lock") {
targetMoved() && lockTargetRotation(target, true, quat);
return;
}
if (this.lockTargetRotation === "dynamic-follow") {
targetMoved() && followTargetRotation(target, true);
return;
}
lockTargetRotation(target, false, quat);
});
return () => {
handle.cancel();
};
}, [this.targetState.get, getCentripetal]);
this.createEffect(() => {
const target = this.targetState.get();
const selectionTarget = getSelectionTarget();
const dragging = getTransformControlsDragging();
const mode = getEditorModeComputed();
const rotating = target &&
target === selectionTarget &&
dragging &&
mode === "rotate";
if (!rotating)
return;
transformControlRotating = true;
return () => {
transformControlRotating = false;
};
}, [
this.targetState.get,
getSelectionTarget,
getTransformControlsDragging,
getEditorModeComputed
]);
}
lockTargetRotation = true;
}
//# sourceMappingURL=index.js.map