2019-02-10 19:30:39 +08:00

1517 lines
50 KiB
JavaScript

import BaseComponent from './BaseComponent';
import SetMaterialCommand from '../command/SetMaterialCommand';
import SetMaterialColorCommand from '../command/SetMaterialColorCommand';
import SetMaterialValueCommand from '../command/SetMaterialValueCommand';
import SetMaterialMapCommand from '../command/SetMaterialMapCommand';
import ShaderMaterialVertex from './shader/shader_material_vertex.glsl';
import ShaderMaterialFragment from './shader/shader_material_fragment.glsl';
import RawShaderMaterialVertex from './shader/raw_shader_material_vertex.glsl';
import RawShaderMaterialFragment from './shader/raw_shader_material_fragment.glsl';
import TextureSelectControl from '../editor/control/TextureSelectControl';
import TextureSettingWindow from '../editor/window/TextureSettingWindow';
import MaterialsSerializer from '../serialization/material/MaterialsSerializer';
import MaterialUtils from '../utils/MaterialUtils';
import Ajax from '../utils/Ajax';
import Converter from '../utils/Converter';
/**
* 材质组件
* @author mrdoob / http://mrdoob.com/
* @author tengge / https://github.com/tengge1
* @param {*} options
*/
function MaterialComponent(options) {
BaseComponent.call(this, options);
this.selected = null;
}
MaterialComponent.prototype = Object.create(BaseComponent.prototype);
MaterialComponent.prototype.constructor = MaterialComponent;
MaterialComponent.prototype.render = function () {
var data = {
xtype: 'div',
id: 'materialPanel',
scope: this.id,
parent: this.parent,
cls: 'Panel',
style: {
display: 'none'
},
children: [{
xtype: 'row',
children: [{
xtype: 'label',
style: {
color: '#555',
fontWeight: 'bold'
},
text: L_MATERIAL_COMPONENT
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: ''
}, {
xtype: 'button',
text: L_SAVE,
onClick: this.onSave.bind(this)
}, {
xtype: 'button',
text: L_SELECT,
onClick: this.onLoad.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: L_TYPE
}, {
xtype: 'select',
id: 'type',
scope: this.id,
options: {
'LineBasicMaterial': L_LINE_BASIC_MATERIAL,
'LineDashedMaterial': L_LINE_DASHED_MATERIAL,
'MeshBasicMaterial': L_MESH_BASIC_MATERIAL,
'MeshDepthMaterial': L_MESH_DEPTH_MATERIAL,
'MeshNormalMaterial': L_MESH_NORMAL_MATERIAL,
'MeshLambertMaterial': L_MESH_LAMBERT_MATERIAL,
'MeshPhongMaterial': L_MESH_PHONG_MATERIAL,
'PointCloudMaterial': L_POINT_CLOUD_MATERIAL,
'MeshStandardMaterial': L_MESH_STANDARD_MATERIAL,
'MeshPhysicalMaterial': L_MESH_PHYSICAL_MATERIAL,
'SpriteMaterial': L_SPRITE_MATERIAL,
'ShaderMaterial': L_SHADER_MATERIAL,
'RawShaderMaterial': L_RAW_SHADER_MATERIAL
},
style: {
width: '100px',
fontSize: '12px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'programRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_SHADER_PROGRAM
}, {
xtype: 'button',
scope: this.id,
text: L_INFO,
style: {
marginLeft: '4px'
},
onClick: this.editProgramInfo.bind(this)
}, {
xtype: 'button',
scope: this.id,
text: L_VERTEX,
style: {
marginLeft: '4px'
},
onClick: this.editVertexShader.bind(this)
}, {
xtype: 'button',
scope: this.id,
text: L_FRAGMENT,
style: {
marginLeft: '4px'
},
onClick: this.editFragmentShader.bind(this)
}]
}, {
xtype: 'row',
id: 'colorRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_COLOR
}, {
xtype: 'color',
id: 'color',
scope: this.id,
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'roughnessRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_ROUGHNESS
}, {
xtype: 'number',
id: 'roughness',
scope: this.id,
value: 0.5,
style: {
width: '60px'
},
range: [0, 1],
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'metalnessRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_METALNESS
}, {
xtype: 'number',
id: 'metalness',
scope: this.id,
value: 0.5,
style: {
width: '60px'
},
range: [0, 1],
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'emissiveRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_EMISSIVE
}, {
xtype: 'color',
id: 'emissive',
scope: this.id,
value: 0x000000,
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'specularRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_SPECULAR
}, {
xtype: 'color',
id: 'specular',
scope: this.id,
value: 0x111111,
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'shininessRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_SHININESS
}, {
xtype: 'number',
id: 'shininess',
scope: this.id,
value: 30,
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'clearCoatRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_CLEAR_COAT
}, {
xtype: 'number',
id: 'clearCoat',
scope: this.id,
value: 1,
style: {
width: '60px'
},
range: [0, 1],
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'clearCoatRoughnessRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_CLEAR_COAT_ROUGHNESS
}, {
xtype: 'number',
id: 'clearCoatRoughness',
scope: this.id,
value: 1,
style: {
width: '60px'
},
range: [0, 1],
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'vertexColorsRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_VERTEX_COLOR
}, {
xtype: 'select',
id: 'vertexColors',
scope: this.id,
options: {
0: L_NO_COLORS,
1: L_FACE_COLORS,
2: L_VERTEX_COLORS
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'skinningRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_SKIN
}, {
xtype: 'checkbox',
id: 'skinning',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'mapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_TEXTURE
}, {
xtype: 'checkbox',
id: 'mapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
},
new TextureSelectControl({
app: this.app,
id: 'map',
scope: this.id,
onChange: this.updateMaterial.bind(this)
}), {
xtype: 'linkbutton',
text: L_SET_MAP,
style: {
marginLeft: '4px'
},
onClick: this.onSetMap.bind(this)
}]
}, {
xtype: 'row',
id: 'alphaMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_ALPHA_MAP
}, {
xtype: 'checkbox',
id: 'alphaMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'alphaMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'bumpMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_BUMP_MAP
}, {
xtype: 'checkbox',
id: 'bumpMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'bumpMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
}), {
xtype: 'number',
id: 'bumpScale',
scope: this.id,
value: 1,
style: {
width: '30px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'normalMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_NORMAL_MAP
}, {
xtype: 'checkbox',
id: 'normalMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'normalMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'displacementMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_DISPLACEMENT_MAP
}, {
xtype: 'checkbox',
id: 'displacementMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'displacementMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
}), {
xtype: 'number',
id: 'displacementScale',
scope: this.id,
value: 1,
style: {
width: '30px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'roughnessMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_ROUGHNESS_MAP
}, {
xtype: 'checkbox',
id: 'roughnessMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'roughnessMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'metalnessMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_METALNESS_MAP
}, {
xtype: 'checkbox',
id: 'metalnessMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'metalnessMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'specularMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_SPECULAR_MAP
}, {
xtype: 'checkbox',
id: 'specularMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'specularMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'envMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_ENV_MAP
}, {
xtype: 'checkbox',
id: 'envMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'envMap',
scope: this.id,
mapping: THREE.SphericalReflectionMapping,
onChange: this.updateMaterial.bind(this)
}), {
xtype: 'number',
id: 'reflectivity',
scope: this.id,
value: 1,
style: {
width: '30px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'lightMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_LIGHT_MAP
}, {
xtype: 'checkbox',
id: 'lightMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'lightMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'aoMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_AO_MAP
}, {
xtype: 'checkbox',
id: 'aoMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'aoMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
}), {
xtype: 'number',
id: 'aoScale',
scope: this.id,
value: 1,
range: [0, 1],
style: {
width: '30px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'emissiveMapRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_EMISSIVE_MAP
}, {
xtype: 'checkbox',
id: 'emissiveMapEnabled',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, new TextureSelectControl({
app: this.app,
id: 'emissiveMap',
scope: this.id,
onChange: this.updateMaterial.bind(this)
})]
}, {
xtype: 'row',
id: 'sideRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_SIDE
}, {
xtype: 'select',
id: 'side',
scope: this.id,
options: {
0: L_FRONT_SIDE,
1: L_BACK_SIDE,
2: L_DOUBLE_SIDE
},
style: {
width: '100px',
fontSize: '12px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'flatShadingRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_FLAT_SHADING
}, {
xtype: 'checkbox',
id: 'flatShading',
scope: this.id,
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'blendingRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_BLENDING
}, {
xtype: 'select',
id: 'blending',
scope: this.id,
options: {
0: L_NO_BLENDING,
1: L_NORMAL_BLENDING,
2: L_ADDITIVE_BLENDING,
3: L_SUBSTRACTIVE_BLENDING,
4: L_MULTIPLY_BLENDING,
5: L_CUSTOM_BLENDING
},
style: {
width: '100px',
fontSize: '12px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'opacityRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_OPACITY
}, {
xtype: 'number',
id: 'opacity',
scope: this.id,
value: 1,
style: {
width: '60px'
},
range: [0, 1],
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'transparentRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_TRANSPARENT
}, {
xtype: 'checkbox',
id: 'transparent',
scope: this.id,
style: {
left: '100px'
},
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'alphaTestRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_ALPHA_TEST
}, {
xtype: 'number',
id: 'alphaTest',
scope: this.id,
style: {
width: '60px'
},
range: [0, 1],
onChange: this.updateMaterial.bind(this)
}]
}, {
xtype: 'row',
id: 'wireframeRow',
scope: this.id,
children: [{
xtype: 'label',
text: L_WIREFRAME
}, {
xtype: 'checkbox',
id: 'wireframe',
scope: this.id,
value: false,
onChange: this.updateMaterial.bind(this)
}, {
xtype: 'number',
id: 'wireframeLinewidth',
scope: this.id,
value: 1,
style: {
width: '60px'
},
range: [0, 100],
onChange: this.updateMaterial.bind(this)
}]
}]
};
var control = UI.create(data);
control.render();
this.app.on(`objectSelected.${this.id}`, this.onObjectSelected.bind(this));
this.app.on(`objectChanged.${this.id}`, this.onObjectChanged.bind(this));
};
MaterialComponent.prototype.onObjectSelected = function () {
this.updateUI();
};
MaterialComponent.prototype.onObjectChanged = function () {
this.updateUI();
};
MaterialComponent.prototype.updateUI = function () {
var container = UI.get('materialPanel', this.id);
var editor = this.app.editor;
if (editor.selected &&
(editor.selected instanceof THREE.Mesh ||
editor.selected instanceof THREE.Line ||
editor.selected instanceof THREE.Sprite) &&
!Array.isArray(editor.selected.material)) {
container.dom.style.display = '';
} else {
container.dom.style.display = 'none';
return;
}
this.selected = editor.selected;
this.setRowVisibility();
this.setRowValue();
};
MaterialComponent.prototype.setRowVisibility = function () {
var programRow = UI.get('programRow', this.id);
var colorRow = UI.get('colorRow', this.id);
var roughnessRow = UI.get('roughnessRow', this.id);
var metalnessRow = UI.get('metalnessRow', this.id);
var emissiveRow = UI.get('emissiveRow', this.id);
var specularRow = UI.get('specularRow', this.id);
var shininessRow = UI.get('shininessRow', this.id);
var clearCoatRow = UI.get('clearCoatRow', this.id);
var clearCoatRoughnessRow = UI.get('clearCoatRoughnessRow', this.id);
var vertexColorsRow = UI.get('vertexColorsRow', this.id);
var skinningRow = UI.get('skinningRow', this.id);
var mapRow = UI.get('mapRow', this.id);
var alphaMapRow = UI.get('alphaMapRow', this.id);
var bumpMapRow = UI.get('bumpMapRow', this.id);
var normalMapRow = UI.get('normalMapRow', this.id);
var displacementMapRow = UI.get('displacementMapRow', this.id);
var roughnessMapRow = UI.get('roughnessMapRow', this.id);
var metalnessMapRow = UI.get('metalnessMapRow', this.id);
var specularMapRow = UI.get('specularMapRow', this.id);
var envMapRow = UI.get('envMapRow', this.id);
var lightMapRow = UI.get('lightMapRow', this.id);
var aoMapRow = UI.get('aoMapRow', this.id);
var emissiveMapRow = UI.get('emissiveMapRow', this.id);
var sideRow = UI.get('sideRow', this.id);
var flatShadingRow = UI.get('flatShadingRow', this.id);
var blendingRow = UI.get('blendingRow', this.id);
var opacityRow = UI.get('opacityRow', this.id);
var transparentRow = UI.get('transparentRow', this.id);
var alphaTestRow = UI.get('alphaTestRow', this.id);
var wireframeRow = UI.get('wireframeRow', this.id);
var properties = {
'vertexShader': programRow,
'color': colorRow,
'roughness': roughnessRow,
'metalness': metalnessRow,
'emissive': emissiveRow,
'specular': specularRow,
'shininess': shininessRow,
'clearCoat': clearCoatRow,
'clearCoatRoughness': clearCoatRoughnessRow,
'vertexColors': vertexColorsRow,
'skinning': skinningRow,
'map': mapRow,
'alphaMap': alphaMapRow,
'bumpMap': bumpMapRow,
'normalMap': normalMapRow,
'displacementMap': displacementMapRow,
'roughnessMap': roughnessMapRow,
'metalnessMap': metalnessMapRow,
'specularMap': specularMapRow,
'envMap': envMapRow,
'lightMap': lightMapRow,
'aoMap': aoMapRow,
'emissiveMap': emissiveMapRow,
'side': sideRow,
'flatShading': flatShadingRow,
'blending': blendingRow,
'opacity': opacityRow,
'transparent': transparentRow,
'alphaTest': alphaTestRow,
'wireframe': wireframeRow
};
var material = this.selected.material;
for (var property in properties) {
properties[property].dom.style.display = material[property] === undefined ? 'none' : ''
}
};
MaterialComponent.prototype.setRowValue = function () {
var type = UI.get('type', this.id);
var color = UI.get('color', this.id);
var roughness = UI.get('roughness', this.id);
var metalness = UI.get('metalness', this.id);
var emissive = UI.get('emissive', this.id);
var specular = UI.get('specular', this.id);
var shininess = UI.get('shininess', this.id);
var clearCoat = UI.get('clearCoat', this.id);
var clearCoatRoughness = UI.get('clearCoatRoughness', this.id);
var vertexColors = UI.get('vertexColors', this.id);
var skinning = UI.get('skinning', this.id);
var mapEnabled = UI.get('mapEnabled', this.id);
var map = UI.get('map', this.id);
var alphaMapEnabled = UI.get('alphaMapEnabled', this.id);
var alphaMap = UI.get('alphaMap', this.id);
var bumpMapEnabled = UI.get('bumpMapEnabled', this.id);
var bumpMap = UI.get('bumpMap', this.id);
var bumpScale = UI.get('bumpScale', this.id);
var normalMapEnabled = UI.get('normalMapEnabled', this.id);
var normalMap = UI.get('normalMap', this.id);
var displacementMapEnabled = UI.get('displacementMapEnabled', this.id);
var displacementMap = UI.get('displacementMap', this.id);
var displacementScale = UI.get('displacementScale', this.id);
var roughnessMapEnabled = UI.get('roughnessMapEnabled', this.id);
var roughnessMap = UI.get('roughnessMap', this.id);
var metalnessMapEnabled = UI.get('metalnessMapEnabled', this.id);
var metalnessMap = UI.get('metalnessMap', this.id);
var specularMapEnabled = UI.get('specularMapEnabled', this.id);
var specularMap = UI.get('specularMap', this.id);
var envMapEnabled = UI.get('envMapEnabled', this.id);
var envMap = UI.get('envMap', this.id);
var reflectivity = UI.get('reflectivity', this.id);
var lightMapEnabled = UI.get('lightMapEnabled', this.id);
var lightMap = UI.get('lightMap', this.id);
var aoMapEnabled = UI.get('aoMapEnabled', this.id);
var aoMap = UI.get('aoMap', this.id);
var aoScale = UI.get('aoScale', this.id);
var emissiveMapEnabled = UI.get('emissiveMapEnabled', this.id);
var emissiveMap = UI.get('emissiveMap', this.id);
var side = UI.get('side', this.id);
var flatShading = UI.get('flatShading', this.id);
var blending = UI.get('blending', this.id);
var opacity = UI.get('opacity', this.id);
var transparent = UI.get('transparent', this.id);
var alphaTest = UI.get('alphaTest', this.id);
var wireframe = UI.get('wireframe', this.id);
var wireframeLinewidth = UI.get('wireframeLinewidth', this.id);
var material = this.selected.material;
type.setValue(material.type);
if (material.color) {
color.setHexValue(material.color.getHexString());
}
if (material.roughness !== undefined) {
roughness.setValue(material.roughness);
}
if (material.metalness !== undefined) {
metalness.setValue(material.metalness);
}
if (material.emissive !== undefined) {
emissive.setHexValue(material.emissive.getHexString());
}
if (material.specular !== undefined) {
specular.setHexValue(material.specular.getHexString());
}
if (material.shininess !== undefined) {
shininess.setValue(material.shininess);
}
if (material.clearCoat !== undefined) {
clearCoat.setValue(material.clearCoat);
}
if (material.clearCoatRoughness !== undefined) {
clearCoatRoughness.setValue(material.clearCoatRoughness);
}
if (material.vertexColors !== undefined) {
vertexColors.setValue(material.vertexColors);
}
if (material.skinning !== undefined) {
skinning.setValue(material.skinning);
}
if (material.map) {
mapEnabled.setValue(material.map !== null);
if (material.map !== null) {
map.setValue(material.map);
}
}
if (material.alphaMap !== undefined) {
alphaMapEnabled.setValue(material.alphaMap !== null);
if (material.alphaMap !== null) {
alphaMap.setValue(material.alphaMap);
}
}
if (material.bumpMap !== undefined) {
bumpMapEnabled.setValue(material.bumpMap !== null);
if (material.bumpMap !== null) {
bumpMap.setValue(material.bumpMap);
bumpScale.setValue(material.bumpScale);
}
}
if (material.normalMap !== undefined) {
normalMapEnabled.setValue(material.normalMap !== null);
if (material.normalMap !== null) {
normalMap.setValue(material.normalMap);
}
}
if (material.displacementMap !== undefined) {
displacementMapEnabled.setValue(material.displacementMap !== null);
if (material.displacementMap !== null) {
displacementMap.setValue(material.displacementMap);
displacementScale.setValue(material.displacementScale);
}
}
if (material.roughnessMap !== undefined) {
roughnessMapEnabled.setValue(material.roughnessMap !== null);
if (material.roughnessMap !== null) {
roughnessMap.setValue(material.roughnessMap);
}
}
if (material.metalnessMap !== undefined) {
metalnessMapEnabled.setValue(material.metalnessMap !== null);
if (material.metalnessMap !== null) {
metalnessMap.setValue(material.metalnessMap);
}
}
if (material.specularMap !== undefined) {
specularMapEnabled.setValue(material.specularMap !== null);
if (material.specularMap !== null) {
specularMap.setValue(material.specularMap);
}
}
if (material.envMap !== undefined) {
envMapEnabled.setValue(material.envMap !== null);
if (material.envMap !== null) {
envMap.setValue(material.envMap);
}
}
if (material.reflectivity !== undefined) {
reflectivity.setValue(material.reflectivity);
}
if (material.lightMap !== undefined) {
lightMapEnabled.setValue(material.lightMap !== null);
if (material.lightMap !== null) {
lightMap.setValue(material.lightMap);
}
}
if (material.aoMap !== undefined) {
aoMapEnabled.setValue(material.aoMap !== null);
if (material.aoMap !== null) {
aoMap.setValue(material.aoMap);
aoScale.setValue(material.aoMapIntensity);
}
}
if (material.emissiveMap !== undefined) {
emissiveMapEnabled.setValue(material.emissiveMap !== null);
if (material.emissiveMap !== null) {
emissiveMap.setValue(material.emissiveMap);
}
}
if (material.side !== undefined) {
side.setValue(material.side);
}
if (material.flatShading !== undefined) {
flatShading.setValue(material.flatShading);
}
if (material.blending !== undefined) {
blending.setValue(material.blending);
}
if (material.opacity !== undefined) {
opacity.setValue(material.opacity);
}
if (material.transparent !== undefined) {
transparent.setValue(material.transparent);
}
if (material.alphaTest !== undefined) {
alphaTest.setValue(material.alphaTest);
}
if (material.wireframe !== undefined) {
wireframe.setValue(material.wireframe);
}
if (material.wireframeLinewidth !== undefined) {
wireframeLinewidth.setValue(material.wireframeLinewidth);
}
};
MaterialComponent.prototype.updateMaterial = function () {
var type = UI.get('type', this.id);
var color = UI.get('color', this.id);
var roughness = UI.get('roughness', this.id);
var metalness = UI.get('metalness', this.id);
var emissive = UI.get('emissive', this.id);
var specular = UI.get('specular', this.id);
var shininess = UI.get('shininess', this.id);
var clearCoat = UI.get('clearCoat', this.id);
var clearCoatRoughness = UI.get('clearCoatRoughness', this.id);
var vertexColors = UI.get('vertexColors', this.id);
var skinning = UI.get('skinning', this.id);
var mapEnabled = UI.get('mapEnabled', this.id);
var map = UI.get('map', this.id);
var alphaMapEnabled = UI.get('alphaMapEnabled', this.id);
var alphaMap = UI.get('alphaMap', this.id);
var bumpMapEnabled = UI.get('bumpMapEnabled', this.id);
var bumpMap = UI.get('bumpMap', this.id);
var bumpScale = UI.get('bumpScale', this.id);
var normalMapEnabled = UI.get('normalMapEnabled', this.id);
var normalMap = UI.get('normalMap', this.id);
var displacementMapEnabled = UI.get('displacementMapEnabled', this.id);
var displacementMap = UI.get('displacementMap', this.id);
var displacementScale = UI.get('displacementScale', this.id);
var roughnessMapEnabled = UI.get('roughnessMapEnabled', this.id);
var roughnessMap = UI.get('roughnessMap', this.id);
var metalnessMapEnabled = UI.get('metalnessMapEnabled', this.id);
var metalnessMap = UI.get('metalnessMap', this.id);
var specularMapEnabled = UI.get('specularMapEnabled', this.id);
var specularMap = UI.get('specularMap', this.id);
var envMapEnabled = UI.get('envMapEnabled', this.id);
var envMap = UI.get('envMap', this.id);
var reflectivity = UI.get('reflectivity', this.id);
var lightMapEnabled = UI.get('lightMapEnabled', this.id);
var lightMap = UI.get('lightMap', this.id);
var aoMapEnabled = UI.get('aoMapEnabled', this.id);
var aoMap = UI.get('aoMap', this.id);
var aoScale = UI.get('aoScale', this.id);
var emissiveMapEnabled = UI.get('emissiveMapEnabled', this.id);
var emissiveMap = UI.get('emissiveMap', this.id);
var side = UI.get('side', this.id);
var flatShading = UI.get('flatShading', this.id);
var blending = UI.get('blending', this.id);
var opacity = UI.get('opacity', this.id);
var transparent = UI.get('transparent', this.id);
var alphaTest = UI.get('alphaTest', this.id);
var wireframe = UI.get('wireframe', this.id);
var wireframeLinewidth = UI.get('wireframeLinewidth', this.id);
var editor = this.app.editor;
var object = this.selected;
var geometry = object.geometry;
var material = object.material;
var textureWarning = false;
var objectHasUvs = false;
if (object instanceof THREE.Sprite) {
objectHasUvs = true;
}
if (geometry instanceof THREE.Geometry && geometry.faceVertexUvs[0].length > 0) {
objectHasUvs = true;
}
if (geometry instanceof THREE.BufferGeometry && geometry.attributes.uv !== undefined) {
objectHasUvs = true;
}
if (material instanceof THREE[type.getValue()] === false) {
material = new THREE[type.getValue()]();
if (material instanceof THREE.ShaderMaterial) {
material.uniforms = {
time: {
value: 1.0
}
};
material.vertexShader = ShaderMaterialVertex;
material.fragmentShader = ShaderMaterialFragment;
}
if (material instanceof THREE.RawShaderMaterial) {
material.uniforms = {
time: {
value: 1.0
}
};
material.vertexShader = RawShaderMaterialVertex;
material.fragmentShader = RawShaderMaterialFragment;
}
editor.execute(new SetMaterialCommand(object, material), L_NEW_MATERIAL + ':' + type.getValue());
}
if (material.color !== undefined && material.color.getHex() !== color.getHexValue()) {
editor.execute(new SetMaterialColorCommand(object, 'color', color.getHexValue()));
}
if (material.roughness !== undefined && Math.abs(material.roughness - roughness.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'roughness', roughness.getValue()));
}
if (material.metalness !== undefined && Math.abs(material.metalness - metalness.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'metalness', metalness.getValue()));
}
if (material.emissive !== undefined && material.emissive.getHex() !== emissive.getHexValue()) {
editor.execute(new SetMaterialColorCommand(object, 'emissive', emissive.getHexValue()));
}
if (material.specular !== undefined && material.specular.getHex() !== specular.getHexValue()) {
editor.execute(new SetMaterialColorCommand(object, 'specular', specular.getHexValue()));
}
if (material.shininess !== undefined && Math.abs(material.shininess - shininess.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'shininess', shininess.getValue()));
}
if (material.clearCoat !== undefined && Math.abs(material.clearCoat - clearCoat.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'clearCoat', clearCoat.getValue()));
}
if (material.clearCoatRoughness !== undefined && Math.abs(material.clearCoatRoughness - clearCoatRoughness.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'clearCoatRoughness', clearCoatRoughness.getValue()));
}
if (material.vertexColors !== undefined) {
if (material.vertexColors !== parseInt(vertexColors.getValue())) {
editor.execute(new SetMaterialValueCommand(object, 'vertexColors', parseInt(vertexColors.getValue())));
}
}
if (material.skinning !== undefined && material.skinning !== skinning.getValue()) {
editor.execute(new SetMaterialValueCommand(object, 'skinning', skinning.getValue()));
}
if (material.map !== undefined) {
var mapEnabled = mapEnabled.getValue() === true;
if (objectHasUvs) {
var map = mapEnabled ? map.getValue() : null;
if (material.map !== map) {
editor.execute(new SetMaterialMapCommand(object, 'map', map));
}
} else {
if (mapEnabled) textureWarning = true;
}
}
if (material.alphaMap !== undefined) {
var mapEnabled = alphaMapEnabled.getValue() === true;
if (objectHasUvs) {
var alphaMap = mapEnabled ? alphaMap.getValue() : null;
if (material.alphaMap !== alphaMap) {
editor.execute(new SetMaterialMapCommand(object, 'alphaMap', alphaMap));
}
} else {
if (mapEnabled) textureWarning = true;
}
}
if (material.bumpMap !== undefined) {
var bumpMapEnabled = bumpMapEnabled.getValue() === true;
if (objectHasUvs) {
var bumpMap = bumpMapEnabled ? bumpMap.getValue() : null;
if (material.bumpMap !== bumpMap) {
editor.execute(new SetMaterialMapCommand(object, 'bumpMap', bumpMap));
}
if (material.bumpScale !== bumpScale.getValue()) {
editor.execute(new SetMaterialValueCommand(object, 'bumpScale', bumpScale.getValue()));
}
} else {
if (bumpMapEnabled) textureWarning = true;
}
}
if (material.normalMap !== undefined) {
var normalMapEnabled = normalMapEnabled.getValue() === true;
if (objectHasUvs) {
var normalMap = normalMapEnabled ? normalMap.getValue() : null;
if (material.normalMap !== normalMap) {
editor.execute(new SetMaterialMapCommand(object, 'normalMap', normalMap));
}
} else {
if (normalMapEnabled) textureWarning = true;
}
}
if (material.displacementMap !== undefined) {
var displacementMapEnabled = displacementMapEnabled.getValue() === true;
if (objectHasUvs) {
var displacementMap = displacementMapEnabled ? displacementMap.getValue() : null;
if (material.displacementMap !== displacementMap) {
editor.execute(new SetMaterialMapCommand(object, 'displacementMap', displacementMap));
}
if (material.displacementScale !== displacementScale.getValue()) {
editor.execute(new SetMaterialValueCommand(object, 'displacementScale', displacementScale.getValue()));
}
} else {
if (displacementMapEnabled) textureWarning = true;
}
}
if (material.roughnessMap !== undefined) {
var roughnessMapEnabled = roughnessMapEnabled.getValue() === true;
if (objectHasUvs) {
var roughnessMap = roughnessMapEnabled ? roughnessMap.getValue() : null;
if (material.roughnessMap !== roughnessMap) {
editor.execute(new SetMaterialMapCommand(object, 'roughnessMap', roughnessMap));
}
} else {
if (roughnessMapEnabled) textureWarning = true;
}
}
if (material.metalnessMap !== undefined) {
var metalnessMapEnabled = metalnessMapEnabled.getValue() === true;
if (objectHasUvs) {
var metalnessMap = metalnessMapEnabled ? metalnessMap.getValue() : null;
if (material.metalnessMap !== metalnessMap) {
editor.execute(new SetMaterialMapCommand(object, 'metalnessMap', metalnessMap));
}
} else {
if (metalnessMapEnabled) textureWarning = true;
}
}
if (material.specularMap !== undefined) {
var specularMapEnabled = specularMapEnabled.getValue() === true;
if (objectHasUvs) {
var specularMap = specularMapEnabled ? specularMap.getValue() : null;
if (material.specularMap !== specularMap) {
editor.execute(new SetMaterialMapCommand(object, 'specularMap', specularMap));
}
} else {
if (specularMapEnabled) textureWarning = true;
}
}
if (material.envMap !== undefined) {
var envMapEnabled = envMapEnabled.getValue() === true;
var envMap = envMapEnabled ? envMap.getValue() : null;
if (material.envMap !== envMap) {
editor.execute(new SetMaterialMapCommand(object, 'envMap', envMap));
}
}
if (material.reflectivity !== undefined) {
var reflectivity = reflectivity.getValue();
if (material.reflectivity !== reflectivity) {
editor.execute(new SetMaterialValueCommand(object, 'reflectivity', reflectivity));
}
}
if (material.lightMap !== undefined) {
var lightMapEnabled = lightMapEnabled.getValue() === true;
if (objectHasUvs) {
var lightMap = lightMapEnabled ? lightMap.getValue() : null;
if (material.lightMap !== lightMap) {
editor.execute(new SetMaterialMapCommand(object, 'lightMap', lightMap));
}
} else {
if (lightMapEnabled) textureWarning = true;
}
}
if (material.aoMap !== undefined) {
var aoMapEnabled = aoMapEnabled.getValue() === true;
if (objectHasUvs) {
var aoMap = aoMapEnabled ? aoMap.getValue() : null;
if (material.aoMap !== aoMap) {
editor.execute(new SetMaterialMapCommand(object, 'aoMap', aoMap));
}
if (material.aoMapIntensity !== aoScale.getValue()) {
editor.execute(new SetMaterialValueCommand(object, 'aoMapIntensity', aoScale.getValue()));
}
} else {
if (aoMapEnabled) textureWarning = true;
}
}
if (material.emissiveMap !== undefined) {
var emissiveMapEnabled = emissiveMapEnabled.getValue() === true;
if (objectHasUvs) {
var emissiveMap = emissiveMapEnabled ? emissiveMap.getValue() : null;
if (material.emissiveMap !== emissiveMap) {
editor.execute(new SetMaterialMapCommand(object, 'emissiveMap', emissiveMap));
}
} else {
if (emissiveMapEnabled) textureWarning = true;
}
}
if (material.side !== undefined) {
var side = parseInt(side.getValue());
if (material.side !== side) {
editor.execute(new SetMaterialValueCommand(object, 'side', side));
}
}
if (material.flatShading !== undefined) {
var flatShading = flatShading.getValue();
if (material.flatShading != flatShading) {
editor.execute(new SetMaterialValueCommand(object, 'flatShading', flatShading));
}
}
if (material.blending !== undefined) {
var blending = parseInt(blending.getValue());
if (material.blending !== blending) {
editor.execute(new SetMaterialValueCommand(object, 'blending', blending));
}
}
if (material.opacity !== undefined && Math.abs(material.opacity - opacity.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'opacity', opacity.getValue()));
}
if (material.transparent !== undefined && material.transparent !== transparent.getValue()) {
editor.execute(new SetMaterialValueCommand(object, 'transparent', transparent.getValue()));
}
if (material.alphaTest !== undefined && Math.abs(material.alphaTest - alphaTest.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'alphaTest', alphaTest.getValue()));
}
if (material.wireframe !== undefined && material.wireframe !== wireframe.getValue()) {
editor.execute(new SetMaterialValueCommand(object, 'wireframe', wireframe.getValue()));
}
if (material.wireframeLinewidth !== undefined && Math.abs(material.wireframeLinewidth - wireframeLinewidth.getValue()) >= 0.01) {
editor.execute(new SetMaterialValueCommand(object, 'wireframeLinewidth', wireframeLinewidth.getValue()));
}
this.updateUI();
if (textureWarning) {
console.warn(`${L_CANNOT_SET_TEXTURE} ${this.selected.name} ${L_MATERIAL_HAS_NO_COORDINATES}`);
}
};
MaterialComponent.prototype.editProgramInfo = function () {
var material = this.selected.material;
var obj = {
defines: material.defines,
uniforms: material.uniforms,
attributes: material.attributes
};
this.app.script.open(material.uuid, this.selected.name + '-ProgramInfo', 'json', JSON.stringify(obj), this.selected.name + `-${L_SHADER_INFO}`, source => {
try {
obj = JSON.parse(source);
material.defines = obj.defines;
material.uniforms = obj.uniforms;
material.attributes = obj.attributes;
material.needsUpdate = true;
} catch (e) {
this.app.error(this.selected.name + `-${L_SHADER_CANNOT_PARSE}`);
}
});
};
MaterialComponent.prototype.editVertexShader = function () {
var material = this.selected.material;
this.app.script.open(material.uuid, this.selected.name + '-VertexShader', 'vertexShader', material.vertexShader, this.selected.name + `-${L_VERTEX_SHADER}`, source => {
material.vertexShader = source;
material.needsUpdate = true;
});
};
MaterialComponent.prototype.editFragmentShader = function () {
var material = this.selected.material;
this.app.script.open(material.uuid, this.selected.name + '-FragmentShader', 'fragmentShader', material.fragmentShader, this.selected.name + `-${L_FRAGMENT_SHADER}`, source => {
material.fragmentShader = source;
material.needsUpdate = true;
});
};
MaterialComponent.prototype.onSetMap = function () {
if (this.mapSettingWindow === undefined) {
this.mapSettingWindow = new TextureSettingWindow({
app: this.app
});
this.mapSettingWindow.render();
}
if (!this.selected.material.map) {
UI.msg(L_SELECT_TEXTURE_FIRST);
return;
}
this.mapSettingWindow.setData(this.selected.material.map);
this.mapSettingWindow.show();
};
// --------------------------------------- 材质保存载入 --------------------------------------------------
MaterialComponent.prototype.onSave = function () {
UI.prompt(L_ENTER_MATERIAL_NAME, L_NAME, L_NEW_MATERIAL, (event, value) => {
this.commitSave(value);
});
};
MaterialComponent.prototype.commitSave = function (name) {
var material = this.selected.material;
var data = (new MaterialsSerializer()).toJSON(material);
// 材质球图片
var dataURL = MaterialUtils.createMaterialImage(material).toDataURL('image/png');
var file = Converter.dataURLtoFile(dataURL, name);
// 上传图片
Ajax.post(`${this.app.options.server}/api/Upload/Upload`, {
file: file
}, result => {
var obj = JSON.parse(result);
Ajax.post(`/api/Material/Save`, {
Name: name,
Data: JSON.stringify(data),
Thumbnail: obj.Data.url
}, result => {
var obj = JSON.parse(result);
if (obj.Code === 200) {
this.app.call(`showBottomPanel`, this, 'material');
}
UI.msg(obj.Msg);
});
});
};
MaterialComponent.prototype.onLoad = function () {
this.app.call(`selectBottomPanel`, this, 'material');
UI.msg(L_CLICK_MATERIAL_ON_PANEL);
this.app.on(`selectMaterial.${this.id}`, this.onWaitingForMaterial.bind(this));
};
MaterialComponent.prototype.onWaitingForMaterial = function (material) {
this.app.on(`selectMaterial.${this.id}`, null);
if (this.selected.material) {
this.selected.material.dispose();
}
this.selected.material = material;
this.app.call('objectChanged', this, this.selected);
};
export default MaterialComponent;