mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
117 lines • 4.5 kB
JavaScript
import fit from "./utils/fit";
import Loaded from "./core/Loaded";
import AnimationManager from "./core/AnimatedObjectManager/AnimationManager";
import { modelDefaults, modelSchema } from "../interface/IModel";
import { Resolvable } from "@lincode/promiselikes";
import { Reactive } from "@lincode/reactivity";
import measure from "./utils/measure";
import { getExtensionIncludingObjectURL } from "./core/utils/objectURL";
import { decreaseLoadingCount, increaseLoadingCount } from "../states/useLoadingCount";
export default class Model extends Loaded {
unmounted;
static componentName = "model";
static defaults = modelDefaults;
static schema = modelSchema;
constructor(unmounted) {
super(unmounted);
this.unmounted = unmounted;
}
loadingState = new Reactive(0);
playAnimation(name, o) {
setTimeout(() => this.cancelHandle("playAnimation", () => this.loadingState.get((count, handle) => {
if (count)
return;
handle.cancel();
super.playAnimation(name, o);
})));
}
stopAnimation() {
setTimeout(() => this.cancelHandle("stopAnimation", () => this.loadingState.get((count, handle) => {
if (count)
return;
handle.cancel();
super.stopAnimation();
})));
}
serializeAnimations;
async loadAnimation(url, name = url) {
;
(this.serializeAnimations ??= {})[name] = url;
const clip = (await this.load(url)).animations[0];
if (!clip)
return;
this.animations[name] = this.watch(new AnimationManager(clip, await this.loaded));
}
get animations() {
return super.animations;
}
set animations(val) {
for (const [key, value] of Object.entries(val))
if (typeof value === "string")
this.loadAnimation(value, key);
else
this.animations[key] = value;
}
async load(url) {
increaseLoadingCount();
const resolvable = new Resolvable();
this.loadingState.set(this.loadingState.get() + 1);
const extension = getExtensionIncludingObjectURL(url);
if (!extension || !["fbx", "glb", "gltf"].includes(extension)) {
resolvable.resolve();
setTimeout(() => this.loadingState.set(this.loadingState.get() - 1));
decreaseLoadingCount();
throw new Error("Unsupported file extension " + extension);
}
const module = extension === "fbx"
? await import("./utils/loaders/loadFBX")
: await import("./utils/loaders/loadGLTF");
let result;
try {
result = await module.default(url, !this.unmounted);
}
catch {
resolvable.resolve();
setTimeout(() => this.loadingState.set(this.loadingState.get() - 1));
decreaseLoadingCount();
throw new Error("Failed to load model, check if src is correct");
}
resolvable.resolve();
setTimeout(() => this.loadingState.set(this.loadingState.get() - 1));
decreaseLoadingCount();
return result;
}
_resize;
get resize() {
return this._resize ?? true;
}
set resize(val) {
this._resize = val;
this.loaded.done && (this.src = this._src);
}
resolveLoaded(loadedObject3d, src) {
if (this.unmounted)
return loadedObject3d;
for (const clip of loadedObject3d.animations)
this.animations[clip.name] = this.watch(new AnimationManager(clip, loadedObject3d));
const measuredSize = this._resize === false
? measure(loadedObject3d, src)
: fit(loadedObject3d, src);
!this.widthSet && (this.object3d.scale.x = measuredSize.x);
!this.heightSet && (this.object3d.scale.y = measuredSize.y);
!this.depthSet && (this.object3d.scale.z = measuredSize.z);
return loadedObject3d;
}
find(name, hiddenFromSceneGraph) {
const child = super.find(name, hiddenFromSceneGraph);
child && (child.model = this);
return child;
}
findAll(name) {
const children = super.findAll(name);
for (const child of children)
child.model = this;
return children;
}
}
//# sourceMappingURL=Model.js.map