Files
cocos-engine/editor/inspector/utils/material.js
袁炜海 a3f348ab89 feat: use index and phase as the effect pass`s name on inspector panel (#15147)
* feat: pass name add phase

* feat: remove default
2023-05-23 17:57:29 +08:00

202 lines
6.0 KiB
JavaScript

'use strict';
/**
* Pass the data of a pass under a technique and organize it into a tree structure
* @param passData
*/
exports.buildEffect = function(index, passData) {
const props = passData.props;
const defs = passData.defines;
const tree = {
name: `Pass ${index}${passData.phase ? ' - ' + passData.phase : ''}`,
type: 'cc.Object',
childMap: {},
};
const hideAttrs = ['USE_INSTANCING'];
function encode(item) {
let current = tree;
/**
* USE_INSTANCING is common to every child in passes
* To make editing easier, they are referred to the outside of the passes
* At this point, you need to set each of the passes to be non-editable and invisible
*/
if (hideAttrs.includes(item.name)) {
item.visible = false;
}
if (item.defines && item.defines.length) {
item.defines.forEach((name) => {
// The defines starting with ! are reverse dependencies, the data position will not change
if (name.startsWith('!')) {
return;
}
let child = current.childMap[name];
if (!child) {
child = current.childMap[name] = {
name,
// type: 'ui.Depend',
type: 'Boolean',
childMap: {},
};
}
current = child;
});
}
if (current.childMap[item.name]) {
const tempChildMap = current.childMap[item.name].childMap;
current.childMap[item.name] = item;
item.childMap = tempChildMap;
} else {
current.childMap[item.name] = item;
item.childMap = {};
}
current.childMap[item.name].name = item.name;
}
defs.forEach((item) => {
switch (item.type) {
case 'Number':
item.type = 'Enum';
item.enumList = [];
for (let i = item.range[0]; i <= item.range[1]; i++) {
item.enumList.push({
name: i,
value: i,
});
}
break;
case 'String':
item.type = 'Enum';
item.enumList = item.options.map((str) => {
return {
name: str,
value: str,
};
});
break;
case 'Enum': break; // Fix the problem that item.type === 'Enum' is reset to 'ui.Depend'
default:
// item.type = 'ui.Depend';
item.type = 'Boolean';
}
encode(item);
});
props.forEach(encode);
function encodeStates(item) {
let current = tree;
if (current.childMap[item.name]) {
const tempChildMap = current.childMap[item.name].childMap;
current.childMap[item.name] = item;
item.childMap = tempChildMap;
} else {
current.childMap[item.name] = item;
item.childMap = {};
}
if (item.isObject && item.value) {
current = current.childMap[item.name];
Object.keys(item.value).forEach((name) => {
let child = current.childMap[name];
if (!child) {
child = current.childMap[name] = {
name,
type: 'cc.Object',
childMap: {},
};
}
});
}
}
function modifyType(item) {
if (!item) {
return;
}
if (item.isObject) {
Object.keys(item.value).forEach((key) => {
modifyType(item.value[key]);
});
} else if (item.isArray) {
item.value.forEach((data) => {
modifyType(data);
});
modifyType(item.elementTypeData);
} else {
switch (item.type) {
case 'Number':
if (item.isEnum) {
item.type = 'Enum';
item.enumList = [];
Object.keys(item.enumData).forEach((key) => {
item.enumList.push({
name: key,
value: item.enumData[key],
});
});
}
break;
}
}
}
modifyType(passData.states);
encodeStates(passData.states);
function translate(item) {
const children = Object.keys(item.childMap).map((name) => {
const child = item.childMap[name];
translate(child);
return child;
});
if (item) {
item.children = children;
}
return item;
}
const dump = translate(tree);
dump.value = tree.childMap;
return dump;
};
exports.materialTechniquePolyfill = function(origin) {
let useInstancing;
const passes = origin.passes.map((data, index) => {
// Merge data.defines and data.props
const pass = exports.buildEffect(index, data);
pass.switch = data.switch;
pass.propertyIndex = data.propertyIndex;
if (!useInstancing && pass.childMap.USE_INSTANCING) {
useInstancing = JSON.parse(JSON.stringify(pass.childMap.USE_INSTANCING));
useInstancing.visible = true;
}
return pass;
});
/**
* USE_INSTANCING is common to every child in passes
* For ease of editing, they are referred to outside of the passes
* Two external variables useInstancing, useBatching are provided to dock
* The value of the first pass takes precedence
*/
const technique = {
name: origin.name,
passes,
useInstancing,
};
return technique;
};