@openhps/core
Version:
Open Hybrid Positioning System - Core component
183 lines (169 loc) • 4.96 kB
JavaScript
import Node from '../core/Node.js';
import { arrayBufferToBase64, base64ToArrayBuffer } from '../core/NodeUtils.js';
import { nodeProxy, float } from '../tsl/TSLBase.js';
import { EventDispatcher } from '../../core/EventDispatcher.js';
/**
* `ScriptableNode` uses this class to manage script inputs and outputs.
*
* @augments Node
*/
class ScriptableValueNode extends Node {
static get type() {
return 'ScriptableValueNode';
}
/**
* Constructs a new scriptable node.
*
* @param {any} [value=null] - The value.
*/
constructor(value = null) {
super();
/**
* A reference to the value.
*
* @private
* @default null
*/
this._value = value;
/**
* Depending on the type of `_value`, this property might cache parsed data.
*
* @private
* @default null
*/
this._cache = null;
/**
* If this node represents an input, this property represents the input type.
*
* @type {?string}
* @default null
*/
this.inputType = null;
/**
* If this node represents an output, this property represents the output type.
*
* @type {?string}
* @default null
*/
this.outputType = null;
/**
* An event dispatcher for managing events.
*
* @type {EventDispatcher}
*/
this.events = new EventDispatcher();
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isScriptableValueNode = true;
}
/**
* Whether this node represents an output or not.
*
* @type {boolean}
* @readonly
* @default true
*/
get isScriptableOutputNode() {
return this.outputType !== null;
}
set value(val) {
if (this._value === val) return;
if (this._cache && this.inputType === 'URL' && this.value.value instanceof ArrayBuffer) {
URL.revokeObjectURL(this._cache);
this._cache = null;
}
this._value = val;
this.events.dispatchEvent({
type: 'change'
});
this.refresh();
}
/**
* The node's value.
*
* @type {any}
*/
get value() {
return this._value;
}
/**
* Dispatches the `refresh` event.
*/
refresh() {
this.events.dispatchEvent({
type: 'refresh'
});
}
/**
* The `value` property usually represents a node or even binary data in form of array buffers.
* In this case, this method tries to return the actual value behind the complex type.
*
* @return {any} The value.
*/
getValue() {
const value = this.value;
if (value && this._cache === null && this.inputType === 'URL' && value.value instanceof ArrayBuffer) {
this._cache = URL.createObjectURL(new Blob([value.value]));
} else if (value && value.value !== null && value.value !== undefined && ((this.inputType === 'URL' || this.inputType === 'String') && typeof value.value === 'string' || this.inputType === 'Number' && typeof value.value === 'number' || this.inputType === 'Vector2' && value.value.isVector2 || this.inputType === 'Vector3' && value.value.isVector3 || this.inputType === 'Vector4' && value.value.isVector4 || this.inputType === 'Color' && value.value.isColor || this.inputType === 'Matrix3' && value.value.isMatrix3 || this.inputType === 'Matrix4' && value.value.isMatrix4)) {
return value.value;
}
return this._cache || value;
}
/**
* Overwritten since the node type is inferred from the value.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {string} The node type.
*/
getNodeType(builder) {
return this.value && this.value.isNode ? this.value.getNodeType(builder) : 'float';
}
setup() {
return this.value && this.value.isNode ? this.value : float();
}
serialize(data) {
super.serialize(data);
if (this.value !== null) {
if (this.inputType === 'ArrayBuffer') {
data.value = arrayBufferToBase64(this.value);
} else {
data.value = this.value ? this.value.toJSON(data.meta).uuid : null;
}
} else {
data.value = null;
}
data.inputType = this.inputType;
data.outputType = this.outputType;
}
deserialize(data) {
super.deserialize(data);
let value = null;
if (data.value !== null) {
if (data.inputType === 'ArrayBuffer') {
value = base64ToArrayBuffer(data.value);
} else if (data.inputType === 'Texture') {
value = data.meta.textures[data.value];
} else {
value = data.meta.nodes[data.value] || null;
}
}
this.value = value;
this.inputType = data.inputType;
this.outputType = data.outputType;
}
}
export default ScriptableValueNode;
/**
* TSL function for creating a scriptable value node.
*
* @tsl
* @function
* @param {any} [value] - The value.
* @returns {ScriptableValueNode}
*/
export const scriptableValue = /*@__PURE__*/nodeProxy(ScriptableValueNode).setParameterLength(1);