@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
187 lines • 8.23 kB
JavaScript
import { GetDirectStoreFromMetadata } from "./decorators.functions.js";
function generateSerializableMember(type, sourceName) {
return (_value, context) => {
if (!context.metadata) {
return;
}
const propertyKey = String(context.name);
const store = GetDirectStoreFromMetadata(context.metadata);
if (!store[propertyKey]) {
store[propertyKey] = { type: type, sourceName: sourceName };
}
};
}
function generateExpandMember(setCallback, targetKey = null) {
return (_value, context) => {
const key = targetKey || "_" + String(context.name);
return {
init(value) {
if (value !== undefined || !(key in this)) {
this[key] = value;
}
return value;
},
get() {
return this[key];
},
set(value) {
// does this object (i.e. vector3) has an equals function? use it!
// Note - not using "with epsilon" here, it is expected te behave like the internal cache does.
if (typeof this[key]?.equals === "function") {
if (this[key].equals(value)) {
return;
}
}
if (this[key] === value) {
return;
}
this[key] = value;
this[setCallback]();
},
};
};
}
export function expandToProperty(callback, targetKey = null) {
return generateExpandMember(callback, targetKey);
}
export function serialize(sourceName) {
return generateSerializableMember(0 /* SerializedFieldType.VALUE */, sourceName);
}
export function serializeAsTexture(sourceName) {
return generateSerializableMember(1 /* SerializedFieldType.TEXTURE */, sourceName);
}
export function serializeAsColor3(sourceName) {
return generateSerializableMember(2 /* SerializedFieldType.COLOR3 */, sourceName);
}
export function serializeAsFresnelParameters(sourceName) {
return generateSerializableMember(3 /* SerializedFieldType.FRESNEL_PARAMETERS */, sourceName);
}
export function serializeAsVector2(sourceName) {
return generateSerializableMember(4 /* SerializedFieldType.VECTOR2 */, sourceName);
}
export function serializeAsVector3(sourceName) {
return generateSerializableMember(5 /* SerializedFieldType.VECTOR3 */, sourceName);
}
export function serializeAsMeshReference(sourceName) {
return generateSerializableMember(6 /* SerializedFieldType.MESH */, sourceName);
}
export function serializeAsColorCurves(sourceName) {
return generateSerializableMember(7 /* SerializedFieldType.COLOR_CURVES */, sourceName);
}
export function serializeAsColor4(sourceName) {
return generateSerializableMember(8 /* SerializedFieldType.COLOR4 */, sourceName);
}
export function serializeAsImageProcessingConfiguration(sourceName) {
return generateSerializableMember(9 /* SerializedFieldType.IMAGE_PROCESSING */, sourceName);
}
export function serializeAsQuaternion(sourceName) {
return generateSerializableMember(10 /* SerializedFieldType.QUATERNION */, sourceName);
}
export function serializeAsMatrix(sourceName) {
return generateSerializableMember(12 /* SerializedFieldType.MATRIX */, sourceName);
}
export function serializeAsVector4(sourceName) {
return generateSerializableMember(13 /* SerializedFieldType.VECTOR4 */, sourceName);
}
/**
* Decorator used to define property that can be serialized as reference to a camera
* @param sourceName defines the name of the property to decorate
* @returns Property Decorator
*/
export function serializeAsCameraReference(sourceName) {
return generateSerializableMember(11 /* SerializedFieldType.CAMERA */, sourceName);
}
/**
* Shared implementation for the {@link nativeOverride} decorator and its `.filter` variant.
* Both flavors install a wrapper that, on first invocation, resolves the function to use once:
* either the original JS function or (when running in a Babylon Native context) a native-aware
* function produced by `resolveNative`. The resolved function then replaces the wrapper on the
* target so subsequent calls skip this setup entirely.
* @param originalMethod - The decorated JS method.
* @param context - The TC39 method decorator context.
* @param resolveNative - Builds the function to use when a native override is present, given the
* native function and the original JS function.
* @returns The wrapper function that replaces the decorated method.
*/
function ApplyNativeOverride(originalMethod, context, resolveNative) {
const propertyKey = String(context.name);
let resolvedFunc = null;
const wrapper = function (...params) {
if (resolvedFunc === null) {
// Default to the original JS function.
resolvedFunc = originalMethod;
// Check if we are executing in a Babylon Native context and if so, check for a function override.
if (typeof _native !== "undefined" && _native[propertyKey]) {
resolvedFunc = resolveNative(_native[propertyKey], originalMethod);
}
const target = (this && (context.static ? this : Object.getPrototypeOf(this)));
if (target?.[propertyKey] === wrapper) {
target[propertyKey] = resolvedFunc;
}
}
return resolvedFunc.apply(this, params);
};
return wrapper;
}
/**
* Decorator used to redirect a function to a native implementation if available.
* @internal
*/
export function nativeOverride(originalMethod, context) {
// When a native override exists, use it directly.
return ApplyNativeOverride(originalMethod, context, (nativeFunc) => nativeFunc);
}
/**
* Decorator factory that applies the nativeOverride decorator, but determines whether to redirect to the native implementation based on a filter function that evaluates the function arguments.
* @param predicate
* @example @nativeOverride.filter((arg1: string) => arg1.length > 20)
* public someMethod(arg1: string, arg2: number): string {
* @internal
*/
nativeOverride.filter = function (predicate) {
return (originalMethod, context) => {
// When a native override exists, evaluate the predicate on each call to choose between the native and JS function.
return ApplyNativeOverride(originalMethod, context, (nativeFunc, jsFunc) => {
return function (...args) {
if (predicate(...args)) {
// The native function is invoked without a `this` binding, matching the original behavior.
return nativeFunc(...args);
}
return jsFunc.apply(this, args);
};
});
};
};
/**
* Adds accessors for a material property.
* Applied to an auto-accessor field. Reads/writes from a private backing field named by sourceKey (default: "_" + property name).
* The backing field is expected to have a `.value` property.
* @param setCallback - The name of the callback function to call when the property is set.
* @param sourceKey - The name of the private field that stores the value (defaults to "_" + accessor name).
* @returns An accessor decorator.
*/
export function addAccessorsForMaterialProperty(setCallback, sourceKey = null) {
return (_value, context) => {
const key = sourceKey || "_" + String(context.name);
return {
get() {
return this[key]?.value;
},
set(value) {
// does this object (i.e. vector3) has an equals function? use it!
// Note - not using "with epsilon" here, it is expected te behave like the internal cache does.
if (typeof this[key]?.value?.equals === "function") {
if (this[key].value.equals(value)) {
return;
}
}
if (this[key].value === value) {
return;
}
this[key].value = value;
this[setCallback]();
},
};
};
}
//# sourceMappingURL=decorators.js.map