@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
198 lines (182 loc) • 7.92 kB
text/typescript
import {TypedParam} from './../../../params/_Base';
import {ParamsUpdateOptions} from '../../utils/params/ParamsController';
import {ParamOptions} from '../../../params/utils/OptionsController';
import {ParamType} from '../../../poly/ParamType';
import {GlAssemblerControllerType, AssemblerGlControllerNode} from './Controller';
import {ParamInitValueSerialized} from '../../../params/types/ParamInitValueSerialized';
import {setToArray, setIntersection, setUnion} from '../../../../core/SetUtils';
import {mapGroupBy} from '../../../../core/MapUtils';
import {GlParamConfig} from './utils/GLParamConfig';
import {arrayToSet} from '../../../../core/ArrayUtils';
const _tmpStrings: string[] = [];
const DEBUG = false;
function _paramMatchesParamConfig<T extends ParamType>(param: TypedParam<T>, paramConfig: GlParamConfig<T>) {
if (param.type() != paramConfig.type()) {
if (DEBUG) {
console.log(`${param.name()}: type is different to paramConfig's`, param.type(), paramConfig.type());
}
return false;
}
if (param.name() != paramConfig.name()) {
if (DEBUG) {
console.log(`${param.name()}: name is different to paramConfig's`, param.name(), paramConfig.name());
}
return false;
}
if (!param.isDefaultValueEqual(paramConfig.defaultValue())) {
if (DEBUG) {
console.log(
`${param.name()}: defaultValue is different to paramConfig's`,
param.defaultValue(),
paramConfig.defaultValue()
);
}
return false;
}
// if (!param.isRawInputEqual(paramConfig.defaultValue())) {
// if (debug) {
// console.log(
// `${param.name()}: rawInput is different to paramConfig's`,
// param.rawInput(),
// paramConfig.defaultValue()
// );
// }
// return false;
// }
return true;
}
/*
Create spare params on mat nodes
*/
export class GlAssemblerNodeSpareParamsController {
// private _deletedParamsData: Map<string, ParamJsonExporterData<ParamType>> = new Map();
// private _createdSpareParamNames: Set<string> = new Set();
private _raw_input_serialized_by_param_name: Map<string, ParamInitValueSerialized> = new Map();
private _init_value_serialized_by_param_name: Map<string, ParamInitValueSerialized> = new Map();
constructor(private _controller: GlAssemblerControllerType, private _node: AssemblerGlControllerNode) {}
get assembler() {
return this._controller.assembler;
}
// private _createdSpareParams(){
// return this._node.params.spare;
// }
createSpareParameters() {
// const current_spare_param_names: string[] = this.node.params.spare_names;
const paramsUpdateOptions: ParamsUpdateOptions = {};
const paramConfigs = this.assembler.param_configs();
const paramConfigsByName = mapGroupBy<GlParamConfig<ParamType>, string>(paramConfigs, (c) => c.name());
const assembler_param_names = paramConfigs.map((c) => c.name());
const spare_param_names_to_add: Set<string> = new Set();
arrayToSet(assembler_param_names, spare_param_names_to_add);
const validation_result = this._validateNames(spare_param_names_to_add);
if (validation_result == false) {
return;
}
// spare_param_names_to_remove is composed of previously created params, but also spare params with the same name, which may be created when loading the scene
// console.log('- 1', this._createSpareParams(), spare_param_names_to_add);
const currentSpareParams = this._node.params.spare;
const spare_param_names_to_remove: Set<string> = new Set();
const currentSpareParamNames: Set<string> = new Set();
arrayToSet(
currentSpareParams.map((p) => p.name()),
currentSpareParamNames
);
setUnion(currentSpareParamNames, spare_param_names_to_add, spare_param_names_to_remove);
// but if the param type has not changed, we do not need to remove it, nor add it
// this._createdSpareParamNames.forEach((paramName) => {
// const currentParamType = this._node.params.get(paramName)?.type();
// const paramConfigsWithName = paramConfigsByName.get(paramName);
// if (paramConfigsWithName) {
// const firstParamConfig = paramConfigsWithName[0];
// if (firstParamConfig) {
// const expectedParamType = firstParamConfig.type();
// if (currentParamType == expectedParamType) {
// spare_param_names_to_remove.delete(paramName);
// spare_param_names_to_add.delete(paramName);
// }
// }
// }
// });
for (const currentSpareParam of currentSpareParams) {
const paramConfigsWithName = paramConfigsByName.get(currentSpareParam.name());
if (paramConfigsWithName) {
const firstParamConfig = paramConfigsWithName[0];
if (firstParamConfig) {
if (_paramMatchesParamConfig(currentSpareParam, firstParamConfig)) {
spare_param_names_to_remove.delete(currentSpareParam.name());
spare_param_names_to_add.delete(currentSpareParam.name());
}
}
}
}
// keep track of raw_inputs so we can restore them
spare_param_names_to_remove.forEach((param_name) => {
// store the param data, in case it gets recreated later
// this allows expressions to be kept in memory
const param = this._node.params.get(param_name);
if (param && !param.parentParam()) {
this._raw_input_serialized_by_param_name.set(param.name(), param.rawInputSerialized());
this._init_value_serialized_by_param_name.set(param.name(), param.defaultValueSerialized());
// const param_exporter = JsonExportDispatcher.dispatch_param(param);
// if (param_exporter.required()) {
// // const params_data = param_exporter.data();
// // this._deletedParamsData.set(param.name(), params_data);
// }
paramsUpdateOptions.namesToDelete = paramsUpdateOptions.namesToDelete || [];
paramsUpdateOptions.namesToDelete.push(param_name);
}
});
// this.within_param_folder('spare_params', () => {
for (const paramConfig of paramConfigs) {
if (spare_param_names_to_add.has(paramConfig.name())) {
// const config_options = ObjectUtils.clone(paramConfig.paramOptions());
const options: ParamOptions = {
spare: true,
computeOnDirty: true,
cook: false, // it should update the uniforms only via its callback
// important for texture nodes
// that compute after being found by the nodepath param
dependentOnFoundNode: true,
};
// const options = ObjectUtils.merge(config_options, default_options);
// set init_value and raw_input to the previous param's
let init_value = this._init_value_serialized_by_param_name.get(paramConfig.name());
if (init_value == null) {
init_value = paramConfig.defaultValue() as any;
}
let raw_input = this._raw_input_serialized_by_param_name.get(paramConfig.name());
if (raw_input == null) {
raw_input = paramConfig.defaultValue() as any;
}
paramsUpdateOptions.toAdd = paramsUpdateOptions.toAdd || [];
paramsUpdateOptions.toAdd.push({
name: paramConfig.name(),
type: paramConfig.type(),
initValue: init_value as any,
rawInput: raw_input as any,
options: options,
});
}
}
this._node.params.updateParams(paramsUpdateOptions);
for (const paramConfig of paramConfigs) {
paramConfig.applyToNode(this._node);
}
}
private _validateNames(spare_param_names_to_add: Set<string>): boolean {
// check that param_names_to_add does not include any currently existing param names (that are not spare)
const currentParamNames: Set<string> = new Set();
arrayToSet(this._node.params.non_spare_names, currentParamNames);
const spareParamsWithSameNameAsParams: Set<string> = new Set();
setIntersection(spare_param_names_to_add, currentParamNames, spareParamsWithSameNameAsParams);
if (spareParamsWithSameNameAsParams.size > 0) {
const error_message = `${this._node.path()} attempts to create spare params called '${setToArray(
spareParamsWithSameNameAsParams,
_tmpStrings
).join(', ')}' with same name as params`;
this._node.states.error.set(error_message);
return false;
}
return true;
}
}