Source: objects/Water.js

import { Utils } from '../common/Utils'
import { BasePlanePoints } from './BasePlanePoints';

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

/**
 * @class Water
 * The water object.
 * @memberof THING
 * @extends THING.BasePlanePoints
 * @public
 */
class Water extends BasePlanePoints {

	static defaultTagArray = ['Region'];

	/**
	 * The water object in scene.
	 * @param {Object} param The initial parameters.
	 */
	constructor(param = {}) {
		super(param);

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

		_private.flowOffset = [0, 0];
		_private.flowSpeed = [0, 0];
		_private.flowWeight = 0.5;
		_private.reflectDistortion = 2;
		_private.noiseTimeScale = 1;

		// Set default normal map
		let normalMap = this.app.global.cache.images['water_normal_image'];
		this.style.normalMap = normalMap;

		this._syncOptions(param);
	}

	// #region Private

	_syncOptions(param) {
		super.onSyncOptions(param);

		Utils.syncOptions(this, [
			'flowSpeed',
			'flowWeight',
			'reflectDistortion',
			'noiseTimeScale',
		], param, param['extras'] || param['external']);
	}

	// #endregion

	// #region Overrides

	onBeforeSetup(param) {
		param['renderableNode'] = param['renderableNode'] || Utils.createObject('Water');

		super.onBeforeSetup(param);
	}

	onCreateBodyNode() {
		let water = Utils.createObject('Water');
		if (!water) {
			return null;
		}

		return water;
	}

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

		let bodyNode = this.bodyNode;
		bodyNode.setFlowWeight(_private.flowWeight);
		bodyNode.setReflectDistortion(_private.reflectDistortion);
		bodyNode.setNoiseTimeScale(_private.noiseTimeScale);
	}

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

		if (_private.flowSpeed[0] || _private.flowSpeed[1]) {
			let factor = deltaTime;
			let flowOffset = _private.flowOffset;
			let flowSpeed = _private.flowSpeed;
			let offset = [flowSpeed[0] * factor, flowSpeed[1] * factor];
			flowOffset[0] += offset[0];
			flowOffset[1] += offset[1];

			this.bodyNode.setFlowOffset(flowOffset);
		}

		this.bodyNode.update(deltaTime);
	}

	onCreate(options) {
		super.onCreate(options);

		this.onAddTickableObject();
	}

	onImportExternalData(external, options) {
		super.onImportExternalData(external, options);
		if (external) {
			this._syncOptions(external);
		}
	}

	// #endregion

	destroy() {
		this.onRemoveTickableObject();

		return super.destroy();
	}

	// #region Accessor

	/**
	 * Get/Set flow speed.
	 * @type {Array<Number>}
	 * @public
	 */
	get flowSpeed() {
		let _private = this[__.private];

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

		_private.flowSpeed = value.concat();
	}

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

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

		_private.flowWeight = value;

		this.bodyNode.setFlowWeight(value);
	}

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

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

		_private.reflectDistortion = value;

		this.bodyNode.setReflectDistortion(value);
	}

	/**
	 * Get/Set noise time scale.
	 * @type {Number}
	 * @public
	 */
	get noiseTimeScale() {
		let _private = this[__.private];

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

		_private.noiseTimeScale = value;

		this.bodyNode.setNoiseTimeScale(value);
	}

	// #endregion

	get isWater() {
		return true;
	}

}

export { Water }