UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

99 lines (87 loc) 3.79 kB
/** * switches between different input values based on an integer input * * @remarks * * For simple use cases where you'd like to switch between 2 values only, use the [gl/TwoWaySwitch](/docs/nodes/gl/TwoWaySwitch) instead. * * * */ import {TypedGlNode} from './_Base'; import {GlConnectionPointType} from '../utils/io/connections/Gl'; import {ShadersCollectionController} from './code/utils/ShadersCollectionController'; import {ThreeToGl} from '../../../core/ThreeToGl'; import {NodeParamsConfig} from '../utils/params/ParamsConfig'; import {CoreMath} from '../../../core/math/_Module'; // force MAX_INPUTS_COUNT to 16 to encourage limiting number of textures for a single vertex shader // see: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#understand_system_limits const MAX_INPUTS_COUNT = 16; class SwitchParamsConfig extends NodeParamsConfig {} const ParamsConfig = new SwitchParamsConfig(); export class SwitchGlNode extends TypedGlNode<SwitchParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return 'switch'; } static INPUT_INDEX = 'index'; override initializeNode() { this.io.connection_points.set_input_name_function(this._gl_input_name.bind(this)); // this.io.connection_points.set_output_name_function(this._gl_output_name.bind(this)); this.io.connection_points.set_expected_input_types_function(this._expected_input_types.bind(this)); this.io.connection_points.set_expected_output_types_function(this._expected_output_types.bind(this)); } protected _gl_input_name(index: number) { if (index == 0) { return SwitchGlNode.INPUT_INDEX; } else { return `in${index - 1}`; } } protected _expected_input_types() { const secondInputType = this.io.connection_points.input_connection_type(1); const type = secondInputType || GlConnectionPointType.FLOAT; const currentConnections = this.io.connections.inputConnections() || []; let lastValidConnectionIndex = 1; let i = 0; for (const connection of currentConnections) { if (connection) { lastValidConnectionIndex = i; } i++; } const expected_count = CoreMath.clamp(lastValidConnectionIndex + 1, 2, MAX_INPUTS_COUNT); const expected_input_types = [GlConnectionPointType.INT]; for (let i = 0; i < expected_count; i++) { expected_input_types.push(type); } return expected_input_types; } protected _expected_output_types() { const input_types = this._expected_input_types(); const type = input_types[1] || GlConnectionPointType.FLOAT; return [type]; } override setLines(shaders_collection_controller: ShadersCollectionController) { const namedOutputConnectionPoints = this.io.outputs.namedOutputConnectionPoints(); if (!namedOutputConnectionPoints) { return; } const var_type: GlConnectionPointType = namedOutputConnectionPoints[0].type(); const out = this.glVarName(this.io.connection_points.output_name(0)); const index_point_name = this.io.connection_points.input_name(0); const arg_index = ThreeToGl.integer(this.variableForInput(index_point_name)); const switch_index_var_name = this.glVarName('index'); const body_lines: string[] = [`${var_type} ${out};`, `int ${switch_index_var_name} = ${arg_index}`]; const lines_count = this._expected_input_types().length - 1; for (let i = 0; i < lines_count; i++) { const if_else = i == 0 ? 'if' : 'else if'; const condition = `${switch_index_var_name} == ${i}`; const connection_point_name = this.io.connection_points.input_name(i + 1); const assignment = `${out} = ${ThreeToGl.any(this.variableForInput(connection_point_name))};`; const body_line = `${if_else}(${condition}){${assignment}}`; body_lines.push(body_line); } shaders_collection_controller.addBodyLines(this, body_lines); } }