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',
];
/**
* @class CameraEffectComponent
* The camera effect compnent.
* @memberof THING
* @extends THING.BaseComponent
* @public
*/
class CameraEffectComponent extends BaseComponent {
/**
* The rendering effect by camera, some object post effect(s) can be changed here.
*/
constructor() {
super();
this[__.private] = {};
let _private = this[__.private];
_private.needsRefresh = false;
/**
* Configuration about glow.
* @typedef {Object} CameraGlowEffect
* @property {Boolean} enable True indicates enable it.
* @property {Number} strength The strength.
* @property {Number} threshold The threshold.
* @property {Number} radius True radius.
*/
_private.glow = {
enable: true,
strength: 1.5,
threshold: 0.001,
radius: 0.4
};
/**
* Configuration about inner glow.
* @typedef {Object} CameraInnerGlowEffect
* @property {Boolean} enable True indicates enable it.
* @property {Array<Number>} color The color.
* @property {Number} strength The strength.
* @property {Number} stride True stride.
*/
_private.innerGlow = {
color: [1, 0, 0, 1],
enable: true,
strength: 2,
stride: 10,
};
/**
* Configuration about tailing.
* @typedef {Object} CameraTailingEffect
* @property {Boolean} enable True indicates enable it.
* @property {Array<Number>} direction The direction.
* @property {Array<Number>} center The center.
*/
_private.tailing = {
enable: true,
direction: [0, 1],
center: [0.5, 0.5]
};
/**
* Configuration about radial.
* @typedef {Object} CameraRadialEffect
* @property {Boolean} enable True indicates enable it.
* @property {Array<Number>} center The center.
*/
_private.radial = {
enable: true,
center: [0.5, 0.5]
};
/**
* Configuration about ghosting.
* @typedef {Object} CameraGhostingEffect
* @property {Boolean} enable True indicates enable it.
* @property {Array<Number>} center The center.
*/
_private.ghosting = {
enable: true,
center: [0.5, 0.5]
};
/**
* Configuration about line bloom.
* @typedef {Object} CameraLineBloomEffect
* @property {Boolean} enable True indicates enable it.
* @property {Number} blendRate The blend rate.
* @property {Number} blurSize The blur size.
* @property {Number} strength The strength.
*/
_private.lineBloom = {
enable: true,
blendRate: 0.7,
blurSize: 1,
strength: 1,
};
_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,
},
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);
// 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
/**
* Enable/Disable.
* @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();
}
/**
* Get the glow.
* @type {CameraGlowEffect}
* @public
*/
get glow() {
return this[__.private].objectProxy.dataProxy.glow;
}
/**
* Get the inner glow.
* @type {CameraInnerGlowEffect}
* @public
*/
get innerGlow() {
return this[__.private].objectProxy.dataProxy.innerGlow;
}
/**
* Get the tailing.
* @type {CameraTailingEffect}
* @public
*/
get tailing() {
return this[__.private].objectProxy.dataProxy.tailing;
}
/**
* Get the radial.
* @type {CameraRadialEffect}
* @public
*/
get radial() {
return this[__.private].objectProxy.dataProxy.radial;
}
/**
* Get the ghosting.
* @type {CameraGhostingEffect}
* @public
*/
get ghosting() {
return this[__.private].objectProxy.dataProxy.ghosting;
}
/**
* Get the lineBloom.
* @type {CameraLineBloomEffect}
* @public
*/
get lineBloom() {
return this[__.private].objectProxy.dataProxy.lineBloom;
}
/**
* Get/Set config.
* @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);
}
/**
* 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 }