168 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			168 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | import Node, { addNodeClass } from '../core/Node.js'; | ||
|  | import { arrayBufferToBase64, base64ToArrayBuffer } from '../core/NodeUtils.js'; | ||
|  | import { addNodeElement, nodeProxy, float } from '../shadernode/ShaderNode.js'; | ||
|  | import { EventDispatcher } from 'three'; | ||
|  | 
 | ||
|  | class ScriptableValueNode extends Node { | ||
|  | 
 | ||
|  | 	constructor( value = null ) { | ||
|  | 
 | ||
|  | 		super(); | ||
|  | 
 | ||
|  | 		this._value = value; | ||
|  | 		this._cache = null; | ||
|  | 
 | ||
|  | 		this.inputType = null; | ||
|  | 		this.outpuType = null; | ||
|  | 
 | ||
|  | 		this.events = new EventDispatcher(); | ||
|  | 
 | ||
|  | 		this.isScriptableValueNode = 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(); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get value() { | ||
|  | 
 | ||
|  | 		return this._value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	refresh() { | ||
|  | 
 | ||
|  | 		this.events.dispatchEvent( { type: 'refresh' } ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	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; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	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; | ||
|  | 
 | ||
|  | export const scriptableValue = nodeProxy( ScriptableValueNode ); | ||
|  | 
 | ||
|  | addNodeElement( 'scriptableValue', scriptableValue ); | ||
|  | 
 | ||
|  | addNodeClass( 'ScriptableValueNode', ScriptableValueNode ); |