Source: objects/BaseShadowLight.js

import { ObjectProxy } from '@uino/base-thing';
import { Utils } from '../common/Utils'
import { BaseLight } from './BaseLight';
import { ShadowLightTransformComponent } from '../components/ShadowLightTransformComponent';
import { ShadowLightAdapterComponent } from '../components/ShadowLightAdapterComponent';
import { ShadowQualityType } from '../const';

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

const registerComponentParam = { isResident: true };

/**
 * @class BaseShadowLight
 * The base shadow light object.
 * @memberof THING
 * @extends THING.BaseLight
 * @public
 */
class BaseShadowLight extends BaseLight {

	/**
	 * The base light object that can cast shadow.
	 * @param {Object} param The initial parameters.
	 */
	constructor(param = {}) {
		super(param);

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

		_private.shadowRange = new ObjectProxy({
			data: {
				width: 64,
				height: 64,
				near: 0.5,
				far: 1000
			},
			onChange: (ev) => {
				this.bodyNode.setShadowRange(ev.data);
			}
		});

		// Set the default values
		if (Utils.isNull(param['shadowQuality'])) {
			this.shadowQuality = ShadowQualityType.High;
		}

		// Sync options
		Utils.syncOptions(this, [
			'enableShadow',
			'shadowQuality',
			'shadowBias',
			'shadowNormalBias',
			'shadowRadius',
			'shadowRange',
			'target'
		], param, param['extras'] || param['external']);

		// Refresh
		this.onRefresh();
	}

	// #region Object3D Overrides

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

		_private.shadowRange.dispose();
		_private.shadowRange = null;

		super.onDestroy();
	}

	onCopy(object) {
		super.onCopy(object);

		this.enableShadow = object.enableShadow;
		this.shadowQuality = object.shadowQuality;
		this.shadowBias = object.shadowBias;
		this.shadowNormalBias = object.shadowNormalBias;
		this.shadowRadius = object.shadowRadius;
		this.shadowRange = object.shadowRange;
		this.target = object.target;
	}

	onRefresh() {
		super.onRefresh();

		let _private = this[__.private];

		_private.shadowRange.notifyChange();
	}

	onSetupComponent(param) {
		super.onSetupComponent(param);

		this.addComponent(ShadowLightTransformComponent, 'transform', registerComponentParam);
		this.addComponent(ShadowLightAdapterComponent, 'adapter', registerComponentParam);
	}

	onUpdate(deltaTime) {
		super.onUpdate(deltaTime);

		this.bodyNode.updateShadow();
	}

	onExportExternalData() {
		let external = Object.assign({}, super.onExportExternalData());
		Utils.setAttributeIfExist(external, 'enableShadow', this);
		Utils.setAttributeIfExist(external, 'shadowQuality', this);
		Utils.setAttributeIfExist(external, 'shadowBias', this);
		Utils.setAttributeIfExist(external, 'shadowNormalBias', this);
		Utils.setAttributeIfExist(external, 'shadowRadius', this);
		Utils.setAttributeIfExist(external, 'shadowRange', this);
		Utils.setAttributeIfExist(external, 'target', this);
		return external;
	}

	// #endregion

	// #region Accessor

	/**
	 * Enable/Disable shadow.
	 * @type {Boolean}
	 * @deprecated 2.7
	 * @private
	 */
	get enableShadow() {
		Utils.warn('Please use castShadow instead');

		return this.castShadow;
	}
	set enableShadow(value) {
		Utils.warn('Please use castShadow instead');

		this.castShadow = value;
	}

	/**
	 * Enable/Disable cast shadow.
	 * @type {Boolean}
	 * @public
	 */
	get castShadow() {
		return this.bodyNode.getCastShadow();
	}
	set castShadow(value) {
		if (this.castShadow == value) {
			return;
		}

		this.bodyNode.setCastShadow(value);

		this.adapter.needRefresh = true;
	}

	/**
	 * Get/Set shadow quality.
	 * @type {ShadowQualityType|Number}
	 * @public
	 */
	get shadowQuality() {
		return this.bodyNode.getShadowQuality();
	}
	set shadowQuality(value) {
		this.bodyNode.setShadowQuality(value);
	}

	/**
	 * Get/Set shadow bias.
	 * @type {Number}
	 * @public
	 */
	get shadowBias() {
		return this.bodyNode.getShadowBias();
	}
	set shadowBias(value) {
		this.bodyNode.setShadowBias(value);
	}

	/**
	 * Get/Set shadow normal bias.
	 * @type {Number}
	 * @public
	 */
	get shadowNormalBias() {
		return this.bodyNode.getShadowNormalBias();
	}
	set shadowNormalBias(value) {
		this.bodyNode.setShadowNormalBias(value);
	}

	/**
	 * Get/Set shadow radius, default is 1 (not working yet).
	 * @type {Number}
	 * @private
	 */
	get shadowRadius() {
		return this.bodyNode.getShadowRadius();
	}
	set shadowRadius(value) {
		this.bodyNode.setShadowRadius(value);
	}

	/**
	 * @typedef {Object} ShadowRangeInfo
	 * @property {Number} width The width.
	 * @property {Number} height The height.
	 * @property {Number} near The near.
	 * @property {Number} far The far.
	 */

	/**
	 * Get/Set shadow range.
	 * @type {ShadowRangeInfo}
	 * @public
	 */
	get shadowRange() {
		let _private = this[__.private];

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

		_private.shadowRange.merge(value);
	}

	// #endregion

	// #region Internal components attributes and functions

	// #region Component - animation

	get target() { return this.transform.target; }

	set target(value) { this.transform.target = value; }

	// #endregion

	// #endregion

	/**
	 * Check whether it's BaseShadowLight type or inherit from it.
	 * @type {Boolean}
	 * @public
	 */
	get isBaseShadowLight() {
		return true;
	}

}

export { BaseShadowLight }