| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- 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 );
|