@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.
86 lines (71 loc) • 2.89 kB
text/typescript
import { Object3D } from "three";
import type { Constructor } from "../../engine/engine_types.js";
const handlers: Map<any, ApplyPrototypeExtension> = new Map();
/** @internal */
export function applyPrototypeExtensions<T>(obj: any, prototype : Constructor<T>) {
if (!obj) return;
// const prototype = Object.getPrototypeOf(obj);
// console.log("TEST", prototype)
if (!prototype) {
console.warn("No prototype found", obj, obj.prototype, obj.constructor);
return;
}
const handler = handlers.get(prototype);
if (handler) {
// console.log("OK", prototype);
handler.apply(obj);
}
// applyPrototypeExtensions(prototype);
}
/** @internal */
export function registerPrototypeExtensions<T>(type: Constructor<T>) {
// console.log("Register", type.prototype.constructor.name);
const handler = createPrototypeExtensionHandler(type.prototype);
handlers.set(type, handler);
}
function createPrototypeExtensionHandler(prototype: any) {
return new ApplyPrototypeExtension(prototype);
}
/** @internal */
export interface IApplyPrototypeExtension {
apply(object: object): void;
}
class ApplyPrototypeExtension implements IApplyPrototypeExtension {
private readonly $symbol: symbol;
private readonly extensions: string[];
private readonly descriptors: Array<PropertyDescriptor | undefined>;
constructor(prototype: object) {
this.$symbol = Symbol("prototype-extension");
// used to decorate cloned object3D objects with the same added components defined above
this.extensions = Object.keys(prototype);
// console.log(this.extensions);
this.descriptors = new Array<PropertyDescriptor | undefined>();
for (let i = 0; i < this.extensions.length; i++) {
const key = this.extensions[i];
// console.log(key);
const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
if (descriptor) {
this.descriptors.push(descriptor);
}
}
}
apply(object: Object3D): void {
if (object[this.$symbol]) return;
object[this.$symbol] = true;
// const prototype = object.constructor.prototype;
for (let i = 0; i < this.extensions.length; i++) {
const key = this.extensions[i];
const desc = this.descriptors[i];
if (desc) {
// if (prototype) {
// const exists = Object.getOwnPropertyDescriptor(prototype, key);
// if (exists) {
// continue;
// }
// }
// console.warn("DEFINE", object, key);
Object.defineProperty(object, key, desc);
}
}
}
}