ShadowEditor/ShadowEditor.Web/src/component/ParticleEmitterComponent.js
liteng 1a2ce3e356 1、粒子发射器预览。
2、修复粒子发射器无法替换纹理bug。
2018-09-16 16:16:20 +08:00

583 lines
18 KiB
JavaScript

import BaseComponent from './BaseComponent';
import SetValueCommand from '../command/SetValueCommand';
/**
* 粒子发射器组件
* @author tengge / https://github.com/tengge1
* @param {*} options
*/
function ParticleEmitterComponent(options) {
BaseComponent.call(this, options);
this.selected = null;
this.isPlaying = false;
}
ParticleEmitterComponent.prototype = Object.create(BaseComponent.prototype);
ParticleEmitterComponent.prototype.constructor = ParticleEmitterComponent;
ParticleEmitterComponent.prototype.render = function () {
var data = {
xtype: 'div',
id: 'particleEmitterPanel',
scope: this.id,
parent: this.parent,
cls: 'Panel',
style: {
display: 'none'
},
children: [{
xtype: 'label',
style: {
width: '100%',
color: '#555',
fontWeight: 'bold'
},
text: '粒子发射器'
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '位置'
}, {
xtype: 'number',
id: 'positionX',
scope: this.id,
onChange: this.onChangePosition.bind(this)
}, {
xtype: 'number',
id: 'positionY',
scope: this.id,
onChange: this.onChangePosition.bind(this)
}, {
xtype: 'number',
id: 'positionZ',
scope: this.id,
onChange: this.onChangePosition.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '位置发散'
}, {
xtype: 'number',
id: 'positionSpreadX',
scope: this.id,
onChange: this.onChangePosition.bind(this)
}, {
xtype: 'number',
id: 'positionSpreadY',
scope: this.id,
onChange: this.onChangePosition.bind(this)
}, {
xtype: 'number',
id: 'positionSpreadZ',
scope: this.id,
onChange: this.onChangePosition.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '速度'
}, {
xtype: 'number',
id: 'velocityX',
scope: this.id,
onChange: this.onChangeVelocity.bind(this)
}, {
xtype: 'number',
id: 'velocityY',
scope: this.id,
onChange: this.onChangeVelocity.bind(this)
}, {
xtype: 'number',
id: 'velocityZ',
scope: this.id,
onChange: this.onChangeVelocity.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '速度发散'
}, {
xtype: 'number',
id: 'velocitySpreadX',
scope: this.id,
onChange: this.onChangeVelocity.bind(this)
}, {
xtype: 'number',
id: 'velocitySpreadY',
scope: this.id,
onChange: this.onChangeVelocity.bind(this)
}, {
xtype: 'number',
id: 'velocitySpreadZ',
scope: this.id,
onChange: this.onChangeVelocity.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '加速度'
}, {
xtype: 'number',
id: 'accelerationX',
scope: this.id,
onChange: this.onChangeAcceleration.bind(this)
}, {
xtype: 'number',
id: 'accelerationY',
scope: this.id,
onChange: this.onChangeAcceleration.bind(this)
}, {
xtype: 'number',
id: 'accelerationZ',
scope: this.id,
onChange: this.onChangeAcceleration.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '加速度发散'
}, {
xtype: 'number',
id: 'accelerationSpreadX',
scope: this.id,
onChange: this.onChangeAcceleration.bind(this)
}, {
xtype: 'number',
id: 'accelerationSpreadY',
scope: this.id,
onChange: this.onChangeAcceleration.bind(this)
}, {
xtype: 'number',
id: 'accelerationSpreadZ',
scope: this.id,
onChange: this.onChangeAcceleration.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '颜色1'
}, {
xtype: 'color',
id: 'color1',
scope: this.id,
onChange: this.onChangeColor.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '颜色2'
}, {
xtype: 'color',
id: 'color2',
scope: this.id,
onChange: this.onChangeColor.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '颜色3'
}, {
xtype: 'color',
id: 'color3',
scope: this.id,
onChange: this.onChangeColor.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '颜色4'
}, {
xtype: 'color',
id: 'color4',
scope: this.id,
onChange: this.onChangeColor.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '尺寸'
}, {
xtype: 'number',
id: 'size',
scope: this.id,
onChange: this.onChangeSize.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '尺寸发散'
}, {
xtype: 'number',
id: 'sizeSpread',
scope: this.id,
onChange: this.onChangeSize.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '纹理'
}, {
xtype: 'texture',
id: 'texture',
scope: this.id,
onChange: this.onChangeTexture.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '粒子数量'
}, {
xtype: 'int',
range: [1, Infinity],
id: 'particleCount',
scope: this.id,
onChange: this.onChangeParticleCount.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '持续时长'
}, {
xtype: 'number',
id: 'maxAge',
scope: this.id,
onChange: this.onChangeMaxAge.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label',
text: '持续时长发散'
}, {
xtype: 'number',
id: 'maxAgeSpread',
scope: this.id,
onChange: this.onChangeMaxAgeSpread.bind(this)
}]
}, {
xtype: 'row',
children: [{
xtype: 'label'
}, {
xtype: 'button',
id: 'btnPreview',
scope: this.id,
text: '预览',
onClick: this.onPreview.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));
};
ParticleEmitterComponent.prototype.onObjectSelected = function () {
this.updateUI();
};
ParticleEmitterComponent.prototype.onObjectChanged = function () {
this.updateUI();
};
ParticleEmitterComponent.prototype.updateUI = function () {
var container = UI.get('particleEmitterPanel', this.id);
var editor = this.app.editor;
if (editor.selected && editor.selected.userData.type === 'ParticleEmitter') {
container.dom.style.display = '';
} else {
container.dom.style.display = 'none';
return;
}
this.selected = editor.selected;
var positionX = UI.get('positionX', this.id);
var positionY = UI.get('positionY', this.id);
var positionZ = UI.get('positionZ', this.id);
var positionSpreadX = UI.get('positionSpreadX', this.id);
var positionSpreadY = UI.get('positionSpreadY', this.id);
var positionSpreadZ = UI.get('positionSpreadZ', this.id);
var velocityX = UI.get('velocityX', this.id);
var velocityY = UI.get('velocityY', this.id);
var velocityZ = UI.get('velocityZ', this.id);
var velocitySpreadX = UI.get('velocitySpreadX', this.id);
var velocitySpreadY = UI.get('velocitySpreadY', this.id);
var velocitySpreadZ = UI.get('velocitySpreadZ', this.id);
var accelerationX = UI.get('accelerationX', this.id);
var accelerationY = UI.get('accelerationY', this.id);
var accelerationZ = UI.get('accelerationZ', this.id);
var accelerationSpreadX = UI.get('accelerationSpreadX', this.id);
var accelerationSpreadY = UI.get('accelerationSpreadY', this.id);
var accelerationSpreadZ = UI.get('accelerationSpreadZ', this.id);
var color1 = UI.get('color1', this.id);
var color2 = UI.get('color2', this.id);
var color3 = UI.get('color3', this.id);
var color4 = UI.get('color4', this.id);
var size = UI.get('size', this.id);
var sizeSpread = UI.get('sizeSpread', this.id);
var texture = UI.get('texture', this.id);
var particleCount = UI.get('particleCount', this.id);
var maxAge = UI.get('maxAge', this.id);
var maxAgeSpread = UI.get('maxAgeSpread', this.id);
var btnPreview = UI.get('btnPreview', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
positionX.setValue(emitter.position.value.x);
positionY.setValue(emitter.position.value.y);
positionZ.setValue(emitter.position.value.z);
positionSpreadX.setValue(emitter.position.spread.x);
positionSpreadY.setValue(emitter.position.spread.y);
positionSpreadZ.setValue(emitter.position.spread.z);
velocityX.setValue(emitter.velocity.value.x);
velocityY.setValue(emitter.velocity.value.y);
velocityZ.setValue(emitter.velocity.value.z);
velocitySpreadX.setValue(emitter.velocity.spread.x);
velocitySpreadY.setValue(emitter.velocity.spread.y);
velocitySpreadZ.setValue(emitter.velocity.spread.z);
accelerationX.setValue(emitter.acceleration.value.x);
accelerationY.setValue(emitter.acceleration.value.y);
accelerationZ.setValue(emitter.acceleration.value.z);
accelerationSpreadX.setValue(emitter.acceleration.spread.x);
accelerationSpreadY.setValue(emitter.acceleration.spread.y);
accelerationSpreadZ.setValue(emitter.acceleration.spread.z);
color1.setValue(`#${emitter.color.value[0].getHexString()}`);
color2.setValue(`#${emitter.color.value[1].getHexString()}`);
color3.setValue(`#${emitter.color.value[2].getHexString()}`);
color4.setValue(`#${emitter.color.value[3].getHexString()}`);
size.setValue(emitter.size.value[0]);
sizeSpread.setValue(emitter.size.spread[0]);
texture.setValue(group.texture);
particleCount.setValue(emitter.particleCount);
maxAge.setValue(emitter.maxAge.value);
maxAgeSpread.setValue(emitter.maxAge.spread);
if (this.isPlaying) {
btnPreview.setText('取消');
} else {
btnPreview.setText('预览');
}
};
ParticleEmitterComponent.prototype.onChangePosition = function () {
var positionX = UI.get('positionX', this.id);
var positionY = UI.get('positionY', this.id);
var positionZ = UI.get('positionZ', this.id);
var positionSpreadX = UI.get('positionSpreadX', this.id);
var positionSpreadY = UI.get('positionSpreadY', this.id);
var positionSpreadZ = UI.get('positionSpreadZ', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.position.value.x = positionX.getValue();
emitter.position.value.y = positionY.getValue();
emitter.position.value.z = positionZ.getValue();
emitter.position.spread.x = positionSpreadX.getValue();
emitter.position.spread.y = positionSpreadY.getValue();
emitter.position.spread.z = positionSpreadZ.getValue();
emitter.updateFlags.position = true;
};
ParticleEmitterComponent.prototype.onChangeVelocity = function () {
var velocityX = UI.get('velocityX', this.id);
var velocityY = UI.get('velocityY', this.id);
var velocityZ = UI.get('velocityZ', this.id);
var velocitySpreadX = UI.get('velocitySpreadX', this.id);
var velocitySpreadY = UI.get('velocitySpreadY', this.id);
var velocitySpreadZ = UI.get('velocitySpreadZ', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.velocity.value.x = velocityX.getValue();
emitter.velocity.value.y = velocityY.getValue();
emitter.velocity.value.z = velocityZ.getValue();
emitter.velocity.spread.x = velocitySpreadX.getValue();
emitter.velocity.spread.y = velocitySpreadY.getValue();
emitter.velocity.spread.z = velocitySpreadZ.getValue();
emitter.updateFlags.velocity = true;
};
ParticleEmitterComponent.prototype.onChangeAcceleration = function () {
var accelerationX = UI.get('accelerationX', this.id);
var accelerationY = UI.get('accelerationY', this.id);
var accelerationZ = UI.get('accelerationZ', this.id);
var accelerationSpreadX = UI.get('accelerationSpreadX', this.id);
var accelerationSpreadY = UI.get('accelerationSpreadY', this.id);
var accelerationSpreadZ = UI.get('accelerationSpreadZ', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.acceleration.value.x = accelerationX.getValue();
emitter.acceleration.value.y = accelerationY.getValue();
emitter.acceleration.value.z = accelerationZ.getValue();
emitter.acceleration.spread.x = accelerationSpreadX.getValue();
emitter.acceleration.spread.y = accelerationSpreadY.getValue();
emitter.acceleration.spread.z = accelerationSpreadZ.getValue();
emitter.updateFlags.acceleration = true;
};
ParticleEmitterComponent.prototype.onChangeColor = function () {
var color1 = UI.get('color1', this.id);
var color2 = UI.get('color2', this.id);
var color3 = UI.get('color3', this.id);
var color4 = UI.get('color4', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.color.value[0] = new THREE.Color(color1.getHexValue());
emitter.color.value[1] = new THREE.Color(color2.getHexValue());
emitter.color.value[2] = new THREE.Color(color3.getHexValue());
emitter.color.value[3] = new THREE.Color(color4.getHexValue());
emitter.updateFlags.color = true;
};
ParticleEmitterComponent.prototype.onChangeSize = function () {
var size = UI.get('size', this.id);
var sizeSpread = UI.get('sizeSpread', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
for (var i = 0; i < emitter.size.value.length; i++) {
emitter.size.value[i] = size.getValue();
emitter.size.spread[i] = sizeSpread.getValue();
}
emitter.updateFlags.size = true;
};
ParticleEmitterComponent.prototype.onChangeTexture = function () {
var texture = UI.get('texture', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
texture = texture.getValue();
texture.needsUpdate = true;
group.texture = texture;
group.material.uniforms.texture.value = texture;
};
ParticleEmitterComponent.prototype.onChangeParticleCount = function () {
var particleCount = UI.get('particleCount', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.particleCount = particleCount.getValue();
emitter.updateFlags.params = true;
};
ParticleEmitterComponent.prototype.onChangeMaxAge = function () {
var maxAge = UI.get('maxAge', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.maxAge.value = maxAge.getValue();
emitter.updateFlags.params = true;
};
ParticleEmitterComponent.prototype.onChangeMaxAgeSpread = function () {
var maxAgeSpread = UI.get('maxAgeSpread', this.id);
var group = this.selected.userData.group;
var emitter = group.emitters[0];
emitter.maxAge.spread = maxAgeSpread.getValue();
emitter.updateFlags.params = true;
};
ParticleEmitterComponent.prototype.onPreview = function () {
if (this.isPlaying) {
this.stopPreview();
} else {
this.startPreview();
}
};
ParticleEmitterComponent.prototype.startPreview = function () {
var btnPreview = UI.get('btnPreview', this.id);
this.isPlaying = true;
btnPreview.setText('取消');
this.app.on(`animate.${this.id}`, this.onAnimate.bind(this));
};
ParticleEmitterComponent.prototype.stopPreview = function () {
var btnPreview = UI.get('btnPreview', this.id);
this.isPlaying = false;
btnPreview.setText('预览');
var group = this.selected.userData.group;
var emitter = this.selected.userData.emitter;
group.removeEmitter(emitter);
group.addEmitter(emitter);
group.tick(0);
this.app.on(`animate.${this.id}`, null);
};
ParticleEmitterComponent.prototype.onAnimate = function (clock, deltaTime) {
var group = this.selected.userData.group;
group.tick(deltaTime);
};
export default ParticleEmitterComponent;