import { ObjectProxy } from '@uino/base-thing';
import { Utils } from '../common/Utils';
import { BaseComponent } from './BaseComponent';
const __ = {
private: Symbol('private'),
}
const cKeys = [
'glow',
'innerGlow',
'tailing',
'radial',
'ghosting',
'lineBloom',
];
/**
* CameraEffectComponent - 相机效果组件
*
* 控制相机渲染效果,可以启用或关闭后处理效果如辉光、模糊等。
* @class CameraEffectComponent
* @memberof THING
* @extends THING.BaseComponent
* @public
* @example
app.camera.effect.enable = true;
app.camera.effect.glow.enable = true;
*/
class CameraEffectComponent extends BaseComponent {
/**
* 相机的渲染效果,可以在这里更改一些对象的后处理效果。
* </br>这里面所有的属性代表整体的一个控制,如需看到效果,需要先把物体身上的对应的effect开启
*/
constructor() {
super();
this[__.private] = {};
let _private = this[__.private];
_private.needsRefresh = false;
/**
发光效果
* @typedef {object} CameraGlowEffect
* @property {boolean} enable 是否开启
* @property {number} strength 强度
* @property {number} threshold 阈值
* @property {number} radius 半径
* @public
*/
_private.glow = {
enable: true,
strength: 1.5,
threshold: 0.001,
radius: 0.4
};
/**
内发光效果
* @typedef {object} CameraInnerGlowEffect
* @property {boolean} enable 是否开启
* @property {Array<number>} color 颜色
* @property {number} strength 强度
* @property {number} stride 跨度
* @public
*/
_private.innerGlow = {
color: [1, 0, 0, 1],
enable: true,
strength: 2,
stride: 10,
};
/**
拖尾效果
* @typedef {object} CameraTailingEffect
* @property {boolean} enable 是否开启
* @property {Array<number>} direction 方向
* @property {Array<number>} center 中心点
* @public
*/
_private.tailing = {
enable: true,
direction: [0, 1],
center: [0.5, 0.5]
};
/**
扩散效果
* @typedef {object} CameraRadialEffect
* @property {boolean} enable 是否开启
* @property {Array<number>} center 中心
* @public
*/
_private.radial = {
enable: true,
center: [0.5, 0.5]
};
/**
残影效果
* @typedef {object} CameraGhostingEffect
* @property {boolean} enable 是否开启
* @property {Array<number>} center 中心位置
* @public
*/
_private.ghosting = {
enable: true,
center: [0.5, 0.5]
};
/**
线辉光效果
* @typedef {object} CameraLineBloomEffect
* @property {boolean} enable 是否开启
* @property {number} blendRate 混合比例
* @property {number} blurSize 模糊半径
* @property {number} strength 强度
* @public
*/
_private.lineBloom = {
enable: true,
blendRate: 0.7,
blurSize: 1,
strength: 1,
};
/**
选中效果
* @typedef {object} CameraLineBloomEffect
* @property {number} thickness 厚度
* @property {number} strength 强度
* @public
*/
_private.outLine = {
strength: 1.5,
thickness: 1.0,
};
_private.onChange = null;
_private.enable = false;
// Initialize config
_private.objectProxy = new ObjectProxy({
data: {
glow: _private.glow,
innerGlow: _private.innerGlow,
tailing: _private.tailing,
radial: _private.radial,
ghosting: _private.ghosting,
lineBloom: _private.lineBloom,
outLine: _private.outLine,
},
onChange: function (ev) {
_private.needsRefresh = true;
if (_private.onChange) {
_private.onChange(ev);
}
}
});
// Show config always
Object.defineProperty(this, 'customFormatters', {
enumerable: false,
configurable: false,
get: function () {
return ['object', { object: _private.objectProxy.dataProxy }];
}
});
}
// #region Private
_refreshEffect() {
let _private = this[__.private];
let cameraNode = this.object.node;
cameraNode.setEffectConfig('glow', _private.glow);
cameraNode.setEffectConfig('innerGlow', _private.innerGlow);
cameraNode.setEffectConfig('tailing', _private.tailing);
cameraNode.setEffectConfig('radial', _private.radial);
cameraNode.setEffectConfig('ghosting', _private.ghosting);
cameraNode.setEffectConfig('lineBloom', _private.lineBloom);
cameraNode.setEffectConfig('outLine', _private.outLine);
// Check whether disable it
if (!_private.enable) {
cKeys.forEach(key => {
cameraNode.setEffectConfig(key, { enable: false });
});
}
}
_refresh() {
let _private = this[__.private];
if (!_private.needsRefresh) {
return;
}
_private.needsRefresh = false;
this._refreshEffect();
}
// #endregion
// #region BaseComponent Overrides
onAdd(object) {
super.onAdd(object);
// Refresh config before render if needed
this.app.addBeforeRenderCallback(this._onBeforeRenderCallback = () => {
this._refresh();
});
// Refresh effect by current config
this._refreshEffect();
}
onRemove() {
let _private = this[__.private];
_private.objectProxy.dispose();
this.app.removeBeforeRenderCallback(this._onBeforeRenderCallback);
super.onRemove();
}
// #endregion
/**
是否开启
* @type {boolean}
* @public
*/
get enable() {
let _private = this[__.private];
return _private.enable;
}
set enable(value) {
let _private = this[__.private];
if (_private.enable == value) {
return;
}
_private.enable = value;
this._refreshEffect();
}
/**
发光效果
* @type {CameraGlowEffect}
* @public
*/
get glow() {
return this[__.private].objectProxy.dataProxy.glow;
}
/**
内发光效果
* @type {CameraInnerGlowEffect}
* @public
*/
get innerGlow() {
return this[__.private].objectProxy.dataProxy.innerGlow;
}
/**
拖尾效果(1.0中的postRadialBlur)
* @type {CameraTailingEffect}
* @public
*/
get tailing() {
return this[__.private].objectProxy.dataProxy.tailing;
}
/**
扩散效果(1.0中的postRadialBlur2)
* @type {CameraRadialEffect}
* @public
*/
get radial() {
return this[__.private].objectProxy.dataProxy.radial;
}
/**
残影效果
* @type {CameraGhostingEffect}
* @public
*/
get ghosting() {
return this[__.private].objectProxy.dataProxy.ghosting;
}
/**
线辉光效果
* @type {CameraLineBloomEffect}
* @public
*/
get lineBloom() {
return this[__.private].objectProxy.dataProxy.lineBloom;
}
/**
选中效果
* @type {CameraLineBloomEffect}
* @public
*/
get outLine() {
return this[__.private].objectProxy.dataProxy.outLine;
}
/**
配置项
* @type {object}
* @public
*/
get config() {
return this[__.private].objectProxy.dataProxy;
}
set config(value = {}) {
let _private = this[__.private];
let to = _private.objectProxy.dataProxy;
Utils.mergeObject(to.glow, value.glow, true);
Utils.mergeObject(to.innerGlow, value.innerGlow, true);
Utils.mergeObject(to.tailing, value.tailing, true);
Utils.mergeObject(to.radial, value.radial, true);
Utils.mergeObject(to.ghosting, value.ghosting, true);
Utils.mergeObject(to.lineBloom, value.lineBloom, true);
Utils.mergeObject(to.outLine, value.outLine, true);
}
/**
Get/Set when change callback function.
* @type {Function}
* @private
*/
get onChange() {
let _private = this[__.private];
return _private.onChange;
}
set onChange(value) {
let _private = this[__.private];
_private.onChange = value;
}
}
export { CameraEffectComponent }