import { MathUtils } from '../../../../build/three.module.js'; class Node { constructor( type ) { this.uuid = MathUtils.generateUUID(); this.name = ''; this.type = type; this.userData = {}; } analyze( builder, settings = {} ) { builder.analyzing = true; this.build( builder.addFlow( settings.slot, settings.cache, settings.context ), 'v4' ); builder.clearVertexNodeCode(); builder.clearFragmentNodeCode(); builder.removeFlow(); builder.analyzing = false; } analyzeAndFlow( builder, output, settings = {} ) { this.analyze( builder, settings ); return this.flow( builder, output, settings ); } flow( builder, output, settings = {} ) { builder.addFlow( settings.slot, settings.cache, settings.context ); const flow = {}; flow.result = this.build( builder, output ); flow.code = builder.clearNodeCode(); flow.extra = builder.context.extra; builder.removeFlow(); return flow; } build( builder, output, uuid ) { output = output || this.getType( builder, output ); const data = builder.getNodeData( uuid || this ); if ( builder.analyzing ) { this.appendDepsNode( builder, data, output ); } if ( builder.nodes.indexOf( this ) === - 1 ) { builder.nodes.push( this ); } if ( this.updateFrame !== undefined && builder.updaters.indexOf( this ) === - 1 ) { builder.updaters.push( this ); } return this.generate( builder, output, uuid ); } generate( /* builder, output, uuid, type, ns */ ) { // This method needs to be implemented in subclasses } getHash() { let hash = '{'; let prop, obj; for ( prop in this ) { obj = this[ prop ]; if ( obj instanceof Node ) { hash += '"' + prop + '":' + obj.getHash() + ','; } } if ( this.hashProperties ) { for ( let i = 0; i < this.hashProperties.length; i ++ ) { prop = this.hashProperties[ i ]; obj = this[ prop ]; hash += '"' + prop + '":"' + String( obj ) + '",'; } } hash += '"id":"' + this.uuid + '"}'; return hash; } appendDepsNode( builder, data, output ) { data.deps = ( data.deps || 0 ) + 1; const outputLen = builder.getTypeLength( output ); if ( outputLen > ( data.outputMax || 0 ) || this.getType( builder, output ) ) { data.outputMax = outputLen; data.output = output; } } setName( name ) { this.name = name; return this; } getName( /* builder */ ) { return this.name; } getType( builder, output ) { return output === 'sampler2D' || output === 'samplerCube' ? output : this.type; } getJSONNode( meta ) { const isRootObject = ( meta === undefined || typeof meta === 'string' ); if ( ! isRootObject && meta.nodes[ this.uuid ] !== undefined ) { return meta.nodes[ this.uuid ]; } } copy( source ) { if ( source.name !== undefined ) this.name = source.name; if ( source.userData !== undefined ) this.userData = JSON.parse( JSON.stringify( source.userData ) ); return this; } createJSONNode( meta ) { const isRootObject = ( meta === undefined || typeof meta === 'string' ); const data = {}; if ( typeof this.nodeType !== 'string' ) throw new Error( 'Node does not allow serialization.' ); data.uuid = this.uuid; data.nodeType = this.nodeType; if ( this.name !== '' ) data.name = this.name; if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; if ( ! isRootObject ) { meta.nodes[ this.uuid ] = data; } return data; } toJSON( meta ) { return this.getJSONNode( meta ) || this.createJSONNode( meta ); } } Node.prototype.isNode = true; Node.prototype.hashProperties = undefined; export { Node };