UNPKG

polygonjs-engine

Version:

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

171 lines (160 loc) 6.11 kB
import {BaseNodeGlMathFunctionArg2GlNode} from './_BaseMathFunction'; import {GlConnectionPointType} from '../utils/io/connections/Gl'; import {ShadersCollectionController} from './code/utils/ShadersCollectionController'; import {ThreeToGl} from '../../../core/ThreeToGl'; interface MathArg2OperationOptions { in_prefix: string; out: string; operation: string; allowed_in_types?: GlConnectionPointType[]; } function MathFunctionArg2OperationFactory(type: string, options: MathArg2OperationOptions) { const in_prefix = options.in_prefix || type; const output_name = options.out || 'val'; const operation = options.operation; const allowed_in_types = options.allowed_in_types; return class Node extends BaseNodeGlMathFunctionArg2GlNode { static type() { return type; } initializeNode() { super.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)); } set_lines(shaders_collection_controller: ShadersCollectionController) { const var_type: GlConnectionPointType = this.io.outputs.named_output_connection_points[0].type(); const args = this.io.inputs.named_input_connection_points.map((connection, i) => { const name = connection.name(); const variable = this.variable_for_input(name); if (variable) { return ThreeToGl.any(variable); } }); const joined_args = args.join(` ${this.gl_operation()} `); const sum = this.gl_var_name(this.io.connection_points.output_name(0)); const body_line = `${var_type} ${sum} = ${this.gl_method_name()}(${joined_args})`; shaders_collection_controller.add_body_lines(this, [body_line]); } _gl_input_name(index: number): string { return `${in_prefix}${index}`; } _gl_output_name(index: number): string { return output_name; } gl_operation(): string { return operation; } protected _expected_input_types() { let first_input_type = this.io.connection_points.first_input_connection_type(); if (first_input_type && allowed_in_types) { if (!allowed_in_types.includes(first_input_type)) { // if the first input type is not allowed, either leave the connection point as is, // or use the default if there is none const first_connection = this.io.inputs.named_input_connection_points[0]; if (first_connection) { first_input_type = first_connection.type(); } } } const type = first_input_type || GlConnectionPointType.FLOAT; const current_connections = this.io.connections.input_connections(); const expected_count = current_connections ? Math.max(current_connections.length + 1, 2) : 2; const expected_input_types = []; 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] || input_types[0] || GlConnectionPointType.FLOAT; return [type]; } }; } export class AddGlNode extends MathFunctionArg2OperationFactory('add', { in_prefix: 'add', out: 'sum', operation: '+', }) {} export class DivideGlNode extends MathFunctionArg2OperationFactory('divide', { in_prefix: 'div', out: 'divide', operation: '/', }) { param_default_value(name: string) { return 1; } } export class SubstractGlNode extends MathFunctionArg2OperationFactory('substract', { in_prefix: 'sub', out: 'substract', operation: '-', }) {} export class MultGlNode extends MathFunctionArg2OperationFactory('mult', { in_prefix: 'mult', out: 'product', operation: '*', }) { static type() { return 'mult'; } param_default_value(name: string) { return 1; } initializeNode() { super.initializeNode(); 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 _expected_output_type() { const input_types = this._expected_input_types(); const type = input_types[input_types.length - 1]; return [type]; } protected _expected_input_types(): GlConnectionPointType[] { const input_connections = this.io.connections.input_connections(); if (input_connections) { const first_connection = input_connections[0]; if (first_connection) { const connection_point_for_first_connection = first_connection.node_src.io.outputs.named_output_connection_points[first_connection.output_index]; // this.io.inputs.named_input_connection_points[ // first_connection.input_index // ]; const type = connection_point_for_first_connection.type(); const expected_count = Math.max(input_connections.length + 1, 2); const empty_array = new Array(expected_count); if (type == GlConnectionPointType.FLOAT) { const second_connection = input_connections[1]; if (second_connection) { const connection_point_for_second_connection = second_connection.node_src.io.outputs.named_output_connection_points[ second_connection.output_index ]; const second_type = connection_point_for_second_connection.type(); if (second_type == GlConnectionPointType.FLOAT) { // if first 2 inputs are float: n+1 float inputs return empty_array.fill(type); } else { // if first input is float and 2nd is different: 1 float, 1 like second, and no other input return [type, second_type]; } } else { // if only 1 input: 2 with same type return [type, type]; } } else { // if first input is not a float: n+1 inputs with same type return empty_array.fill(type); } } else { // if we arrive here, we simply go to the last return statement } } return [GlConnectionPointType.FLOAT, GlConnectionPointType.FLOAT]; } }