Source: components/CameraFogComponent.js

import { ObjectProxy } from '@uino/base-thing';
import { Utils } from '../common/Utils';
import { BaseComponent } from './BaseComponent';
import { FogType } from '../const';

const __ = {
	private: Symbol('private'),
}

/**
 * @class CameraFogComponent
 * The camera fog compnent.
 * @memberof THING
 * @extends THING.BaseComponent
 * @public
 */
class CameraFogComponent extends BaseComponent {

	/**
	 * The fog effect by camera.
	 */
	constructor() {
		super();

		this[__.private] = {};
		let _private = this[__.private];

		_private.needsRefresh = false;

		_private.objectProxy = new ObjectProxy({
			data: {
				enable: false,
				type: FogType.Linear,
				near: 1,
				far: 1000,
				color: [1, 1, 1],
				density: 0.00025
			},
			onChange: function (ev) {
				_private.needsRefresh = true;
			}
		});

		// Refresh effect by current config
		this._refresh();

		// Show config always
		Object.defineProperty(this, 'customFormatters', {
			enumerable: false,
			configurable: false,
			get: function () {
				return ['object', { object: _private.objectProxy.dataProxy }];
			}
		});
	}

	// #region Private Functions

	_refresh() {
		let object = this.object;
		if (!object) {
			return;
		}

		let _private = this[__.private];

		if (!_private.needsRefresh) {
			return;
		}

		_private.needsRefresh = false;

		object.node.setFog(_private.objectProxy.data);
	}

	// #endregion

	// #region BaseComponent Overrides

	onAdd(object) {
		super.onAdd(object);

		// Refresh config before render if needed
		this.app.addBeforeRenderCallback(this._onBeforeRenderCallback = () => {
			this._refresh();
		});
	}

	onRemove() {
		let _private = this[__.private];

		_private.objectProxy.dispose();

		this.app.removeBeforeRenderCallback(this._onBeforeRenderCallback);

		super.onRemove();
	}

	// #endregion

	/**
	 * Enable/Disable fog.
	 * @type {Boolean}
	 * @public
	 */
	get enable() {
		let _private = this[__.private];

		return _private.objectProxy.dataProxy.enable;
	}
	set enable(value) {
		let _private = this[__.private];

		let config = _private.objectProxy.dataProxy;
		if (config.enable == value) {
			return;
		}

		config.enable = value;

		this._refresh();
	}

	/**
	 * Get/Set the type.
	 * @type {FogType}
	 * @public
	 */
	get type() {
		let _private = this[__.private];

		return _private.objectProxy.dataProxy.type;
	}
	set type(value) {
		let _private = this[__.private];

		let config = _private.objectProxy.dataProxy;
		if (config.type == value) {
			return;
		}

		config.type = value;

		this._refresh();
	}

	/**
	 * Get/Set the near.
	 * @type {Number}
	 * @public
	 */
	get near() {
		let _private = this[__.private];

		return _private.objectProxy.dataProxy.near;
	}
	set near(value) {
		let _private = this[__.private];

		let config = _private.objectProxy.dataProxy;
		if (config.near == value) {
			return;
		}

		config.near = value;

		this._refresh();
	}

	/**
	 * Get/Set the far.
	 * @type {Number}
	 * @public
	 */
	get far() {
		let _private = this[__.private];

		return _private.objectProxy.dataProxy.far;
	}
	set far(value) {
		let _private = this[__.private];

		let config = _private.objectProxy.dataProxy;
		if (config.far == value) {
			return;
		}

		config.far = value;

		this._refresh();
	}

	/**
	 * Get/Set the density.
	 * @type {Number}
	 * @public
	 */
	get density() {
		let _private = this[__.private];

		return _private.objectProxy.dataProxy.density;
	}
	set density(value) {
		let _private = this[__.private];

		let config = _private.objectProxy.dataProxy;
		if (config.density == value) {
			return;
		}

		config.density = value;

		this._refresh();
	}

	/**
	 * Get/Set the color.
	 * @type {Number|String|Array<String>}
	 * @public
	 */
	get color() {
		let _private = this[__.private];

		return _private.objectProxy.dataProxy.color;
	}
	set color(value) {
		if (!value) {
			return;
		}

		let _private = this[__.private];
		let config = _private.objectProxy.dataProxy;

		config.color = Utils.parseColor(value);

		this._refresh();
	}

	/**
	 * @typedef {Object} FogInfo
	 * @property {Boolean} enable Enable/Disable fog.
	 * @property {FogType} type The type.
	 * @property {Number} near The near value(for 'Linear' type).
	 * @property {Number} far The far value(for 'Linear' type).
	 * @property {Number} density The density(for 'Exp2' type).
	 * @property {Number|String|Array<String>} color The color.
	 * @public
	 */

	/**
	 * Get/Set config.
	 * @type {FogInfo}
	 * @public
	 */
	get config() {
		return this[__.private].objectProxy.dataProxy;
	}
	set config(value) {
		let _private = this[__.private];

		let to = _private.objectProxy.dataProxy;
		to.enable = Utils.parseValue(value['enable'], to.enable);
		to.type = Utils.parseValue(value['type'], to.type);
		to.color = Utils.parseColor(value['color'], to.color);
		to.density = Utils.parseValue(value['density'], to.density);
		to.near = Utils.parseValue(value['near'], to.near);
		to.far = Utils.parseValue(value['far'], to.far);
	}

}

export { CameraFogComponent }