mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
251 lines • 9.83 kB
JavaScript
import { deg2Rad, endPoint, rad2Deg } from "@lincode/math";
import store, { Reactive } from "@lincode/reactivity";
import { interpret } from "xstate";
import { onBeforeRender } from "../../events/onBeforeRender";
import { onRender } from "../../events/onRender";
import { DUMMY_URL, YBOT_URL } from "../../globals";
import { dummyDefaults, dummySchema } from "../../interface/IDummy";
import Model from "../Model";
import { euler, vector3 } from "../utils/reusables";
import poseMachine from "./poseMachine";
import fpsAlpha from "../utils/fpsAlpha";
import { getCentripetal } from "../../states/useCentripetal";
export const dummyTypeMap = new WeakMap();
export default class Dummy extends Model {
static componentName = "dummy";
static defaults = dummyDefaults;
static schema = dummySchema;
poseService = interpret(poseMachine);
constructor() {
super();
this.width = 20;
this.depth = 20;
this.scale = 1.7;
const [setType, getType] = store(undefined);
const [setSpine, getSpine] = store(undefined);
this.createEffect(() => {
const spineName = this.spineNameState.get();
const src = (super.src = this.srcState.get());
setSpine(undefined);
setType(undefined);
dummyTypeMap.delete(this);
const handle = this.loaded.then((loaded) => {
setType("other");
if (spineName) {
setSpine(this.find(spineName, true));
if (spineName === "mixamorigSpine") {
setType("mixamo");
src === YBOT_URL && dummyTypeMap.set(this, "dummy");
}
else if (spineName === "Spine" &&
(loaded.getObjectByName("Wolf3D_Body") ||
loaded.getObjectByName("Wolf3D_Avatar"))) {
setType("readyplayerme");
dummyTypeMap.set(this, "readyplayerme");
}
return;
}
if (loaded.getObjectByName("Wolf3D_Body") ||
loaded.getObjectByName("Wolf3D_Avatar")) {
setSpine(this.find("Spine", true));
setType("readyplayerme");
dummyTypeMap.set(this, "readyplayerme");
return;
}
const spine = this.find("mixamorigSpine", true);
setSpine(spine);
if (spine) {
setType("mixamo");
src === YBOT_URL && dummyTypeMap.set(this, "dummy");
}
});
return () => {
handle.cancel();
};
}, [this.srcState.get, this.spineNameState.get]);
const [setPose, getPose] = store("idle");
this.createEffect(() => {
const type = getType();
if (!type)
return;
const preset = this.presetState.get();
const prefix = preset === "rifle" ? "rifle-" : "";
const src = this.srcState.get();
const parts = src.split("/");
parts.pop();
let url = parts.join("/") + "/";
if (type === "readyplayerme")
url = DUMMY_URL + "readyplayerme/";
else if (src !== YBOT_URL) {
super.animations = this.animationsState.get();
this.animation = getPose();
return () => {
this.animation = undefined;
};
}
super.animations = {
idle: url + prefix + "idle.fbx",
running: url + prefix + "running.fbx",
runningBackwards: url + prefix + "running-backwards.fbx",
jumping: url + prefix + "falling.fbx",
death: url + "death.fbx",
...this.animationsState.get()
};
this.animation = getPose();
return () => {
this.animation = undefined;
super.animations = {};
};
}, [
this.presetState.get,
this.srcState.get,
getType,
this.animationsState.get
]);
const { poseService } = this;
this.createEffect(() => {
const pose = (this.animation = getPose());
if (pose !== "jumping")
return;
if (getCentripetal()) {
vector3.set(this.velocity.x, this.jumpHeight, this.velocity.z);
vector3.applyMatrix4(this.outerObject3d.matrixWorld);
Object.assign(this.velocity, vector3.multiplyScalar(0.2));
}
else
this.velocity.y = this.jumpHeight;
const handle = onBeforeRender(() => {
this.velocity.y === 0 && poseService.send("JUMP_STOP");
});
return () => {
handle.cancel();
};
}, [getPose]);
poseService
.onTransition((state) => state.changed && setPose(state.value))
.start();
this.then(() => poseService.stop());
this.createEffect(() => {
const loadedItem = this.loadedGroup.children[0];
if (!loadedItem)
return;
const { strideForward, strideRight, strideMove } = this;
if (!strideForward && !strideRight) {
poseService.send("RUN_STOP");
return;
}
let strideMode = this.strideModeState.get();
if (strideMode === "aim" &&
!("runningBackwards" in this.animations))
strideMode = "free";
const backwards = strideMode === "aim" ? strideForward > 0 : false;
const sf = backwards ? -strideForward : strideForward;
const sr = backwards ? strideRight : -strideRight;
const angle = 90 - Math.atan2(-sf, -sr) * rad2Deg;
const spine = getSpine();
const spineQuaternion = spine?.outerObject3d.quaternion.clone();
const loadedItemQuaternion = loadedItem.quaternion.clone();
const handle = onRender(() => {
poseService.send(backwards ? "RUN_BACKWARDS_START" : "RUN_START");
const quaternionOld = loadedItem.quaternion.clone();
let spinePoint;
if (strideMode === "aim" && spine && spineQuaternion) {
loadedItem.quaternion.copy(loadedItemQuaternion);
spine.outerObject3d.quaternion.copy(spineQuaternion);
spinePoint = spine.pointAt(1000);
}
loadedItem.quaternion.setFromEuler(euler.set(0, angle * deg2Rad, 0));
const quaternionNew = loadedItem.quaternion.clone();
loadedItem.quaternion
.copy(quaternionOld)
.slerp(quaternionNew, fpsAlpha(0.2));
spinePoint && spine?.lookAt(spinePoint);
if (!strideMove)
return;
const { x, y } = endPoint(0, 0, angle + 90, Math.max(Math.abs(strideForward), Math.abs(strideRight)));
this.moveForward(backwards ? y : -y);
this.moveRight(backwards ? x : -x);
});
return () => {
if (strideMode === "aim" &&
!this.strideForward &&
!this.strideRight)
loadedItem.quaternion.set(0, 0, 0, 0);
handle.cancel();
};
}, [
this.animationsState.get,
this.strideModeState.get,
this.strideMoveState.get,
this.strideForwardState.get,
this.strideRightState.get,
getSpine
]);
}
spineNameState = new Reactive(undefined);
get spineName() {
return this.spineNameState.get();
}
set spineName(val) {
this.spineNameState.set(val);
}
get resize() {
return super.resize;
}
set resize(val) { }
srcState = new Reactive(YBOT_URL);
get src() {
return this.srcState.get();
}
set src(val) {
this.srcState.set(val);
}
animationsState = new Reactive({});
get animations() {
return super.animations;
}
set animations(val) {
this.animationsState.set(val);
}
presetState = new Reactive("default");
get preset() {
return this.presetState.get();
}
set preset(val) {
this.presetState.set(val);
}
strideForwardState = new Reactive(0);
get strideForward() {
return this.strideForwardState.get();
}
set strideForward(val) {
this.strideForwardState.set(val);
}
strideRightState = new Reactive(0);
get strideRight() {
return this.strideRightState.get();
}
set strideRight(val) {
this.strideRightState.set(val);
}
strideMoveState = new Reactive(false);
get strideMove() {
return this.strideMoveState.get();
}
set strideMove(val) {
this.strideMoveState.set(val);
}
strideModeState = new Reactive("aim");
get strideMode() {
return this.strideModeState.get();
}
set strideMode(val) {
this.strideModeState.set(val);
}
jumpHeight = 10;
jump(height = 10) {
this.jumpHeight = height;
this.poseService.send("JUMP_START");
}
}
//# sourceMappingURL=index.js.map