@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
100 lines (81 loc) • 3.21 kB
text/typescript
import { BufferGeometry,Material, Matrix4, Object3D } from "three";
import { USDDocument,USDObject } from "../../ThreeUSDZExporter.js";
import { ActionBuilder, ActionModel } from "./BehavioursBuilder.js";
export abstract class DocumentAction {
get id(): string { return this.object.uuid; }
protected object: Object3D;
protected model?: USDObject;
constructor(obj: Object3D) {
this.object = obj;
}
apply(document: USDDocument) {
if (!this.model) {
this.model = document.findById(this.object.uuid);
if (!this.model) {
console.error("could not find model with id " + this.object.uuid);
return;
}
}
this.onApply(document);
}
protected abstract onApply(document: USDDocument);
}
export class VariantAction extends DocumentAction {
constructor(obj: Object3D, matrix?: Matrix4, material?: Material, geometry?: BufferGeometry) {
super(obj);
this.matrix = matrix;
this.material = material;
this.geometry = geometry;
}
private matrix: Matrix4 | undefined;
private material: Material | undefined;
private geometry: BufferGeometry | undefined;
protected onApply(_: USDDocument) {
const model = this.model;
if (!model) return;
if (!model.parent?.isDynamic) {
USDObject.createEmptyParent(model);
}
const clone = model.clone();
if (this.matrix) clone.setMatrix(this.matrix);
if (this.material) clone.material = this.material;
if (this.geometry) clone.geometry = this.geometry;
model.parent?.add(clone);
}
private _enableAction?: ActionModel;
private _disableAction?: ActionModel;
enable(): ActionModel {
if (this._enableAction) return this._enableAction;
this._enableAction = ActionBuilder.fadeAction(this.object, 0, true);;
return this._enableAction;
}
disable(): ActionModel {
if (this._disableAction) return this._disableAction;
this._disableAction = ActionBuilder.fadeAction(this.object, 0, false);;
return this._disableAction;
}
}
export class ActionCollection {
private actions: DocumentAction[];
private sortedActions?: { [key: string]: DocumentAction[] };
constructor(actions: DocumentAction[]) {
this.actions = [...actions]
}
// organize is called once when getting an action for the first time
// the sorted actions are baked then and adding new actions will not be added anymore
private organize() {
this.sortedActions = {};
for (const action of this.actions) {
const id = action.id;
if (!this.sortedActions[id]) {
this.sortedActions[id] = [];
}
this.sortedActions[id].push(action);
}
}
/** returns all document actions affecting the object passed in */
getActions(obj: Object3D): DocumentAction[] | null {
if (!this.sortedActions) this.organize();
return this.sortedActions![obj.uuid];
}
}