Source: objects/ExtrudeShape.js

import { Utils } from '../common/Utils'
import { MathUtils } from '../math/MathUtils';
import { BaseDynamicPoints } from './BaseDynamicPoints';

let _originalQuat = [0, 0, 0, 1];

/**
 * @class ExtrudeShape
 * The extrude shape object.
 * @memberof THING
 * @extends THING.BaseDynamicPoints
 * @public
 */
class ExtrudeShape extends BaseDynamicPoints {

	_selfHoles = [];

	_height = 0;

	static defaultTagArray = ['Geometry'];

	/**
	 * The extrude shape object that create polygon shape by height in scene.
	 * @param {Object} param The initial parameters.
	 */
	constructor(param = {}) {
		super(param);

		this._syncOptions(param);
	}

	// #region Private Functions

	/**
	 * Refresh holes.
	 * @private
	 */
	_refreshHoles() {
		let selfPlaneHoles = this.selfPlaneHoles;

		this.bodyNode.setHoles(selfPlaneHoles);
	}

	_syncOptions(param) {
		let bodyNode = this.bodyNode;

		bodyNode.begin();
		{
			super.onSyncOptions(param);

			Utils.syncOptions(this, [
				'selfPlanePoints',
				'selfPlaneHoles',
				'selfHoles',
				'holes',
				'height'
			], param, param['extras'] || param['external']);
		}
		bodyNode.end();
	}

	// #endregion

	// #region Overrides

	onBeforeSetup(param) {
		if (!param['renderableNode']) {
			param['renderableNode'] = Utils.createObject('ExtrudeShape');

			// Use as horz-flat plane shape(Y-axis is up)
			param['renderableNode'].setQuaternion(_originalQuat);
		}

		super.onBeforeSetup(param);
	}

	onAfterSetup(param) {
		super.onAfterSetup(param);
	}

	onGetSelfPoints(selfPoints) {
		return selfPoints.map(point => {
			return [point[0], point[2]];
		});
	}

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

	onExportExternalData() {
		let external = Object.assign({}, super.onExportExternalData());
		Utils.setAttributeIfExist(external, 'selfPlanePoints', this);
		Utils.setAttributeIfExist(external, 'selfPlaneHoles', this);
		Utils.setAttributeIfExist(external, 'selfHoles', this);
		Utils.setAttributeIfExist(external, 'height', this);
		return external;
	}

	// #endregion

	// #region Accessor

	/**
	 * Get/Set the plane points in self space.
	 * @type {Array<Array<Number>>}
	 * @private
	 */
	get selfPlanePoints() {
		return this.points.map(point => {
			let selfPoint = this.worldToSelf(point);

			return [selfPoint[0], selfPoint[2]];
		});
	}
	set selfPlanePoints(value = []) {
		this.points = MathUtils.makeClockWisePoints(value).map(point => {
			return this.selfToWorld([point[0], 0, point[1]]);
		});
	}

	/**
	 * Get/Set the plane holes in self space.
	 * @type {Array<Array<Array<Number>>>}
	 * @private
	 */
	get selfPlaneHoles() {
		return this._selfHoles.map(hole => {
			return hole.map(_hole => {
				return [_hole[0], _hole[2]];
			});
		});
	}
	set selfPlaneHoles(value) {
		this._selfHoles = value.map(hole => {
			return hole.map(_hole => {
				return [_hole[0], 0, _hole[1]];
			});
		});

		this._refreshHoles();
	}

	/**
	 * Get/Set the holes in self space.
	 * @type {Array<Array<Array<Number>>>}
	 * @public
	 */
	get selfHoles() {
		return this._selfHoles;
	}
	set selfHoles(value = []) {
		this._selfHoles = value.slice(0);

		this._refreshHoles();
	}

	/**
	 * Get/Set the holes in world space.
	 * @type {Array<Array<Array<Number>>>}
	 * @public
	 */
	get holes() {
		return this._selfHoles.map(hole => {
			return hole.map(_hole => {
				return this.selfToWorld(_hole);
			});
		});
	}
	set holes(value = []) {
		this._selfHoles = value.map(hole => {
			return hole.map(_hole => {
				return this.worldToSelf(_hole);
			});
		});

		this._refreshHoles();
	}

	/**
	 * Get/Set the height.
	 * @type {Number}
	 * @public
	 */
	get height() {
		return this._height;
	}
	set height(value) {
		this._height = value;

		this.bodyNode.setHeight(value);
	}

	// #endregion

	get isExtrudeShape() {
		return true;
	}

}

export { ExtrudeShape }