Source: exporters/SceneObjectExporter.js

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

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

// #region Private Functions

// Filter object.
function _filterObject(object, options) {
	let lights = Utils.parseValue(options['lights'], false);
	let camera = Utils.parseValue(options['camera'], false);

	if (object.isSubObject) {
		return false;
	}

	if (!lights) {
		if (object.isLight) {
			return false;
		}
	}

	if (!camera) {
		if (object.isCamera) {
			return false;
		}
	}

	return true;
}

// #endregion

/**
 * @class SceneObjectExporter
 * The scene object exporter.
 * @memberof THING
 */
class SceneObjectExporter {

	/**
	 * The exporter to export object(s) in tree mode.
	 * @private
	 */
	constructor() {
		// Initialize private members
		this[__.private] = {};
		let _private = this[__.private];

		_private.sceneExporter = new SceneExporterOld();
	}

	// #region Private

	_exportRootObject(data, object) {
		let _private = this[__.private];

		let rootData = _private.sceneExporter.buildObject(object);

		// Only export these attributes for root object
		let excludeKeys = [
			'type',
			'position',
			'quaterion',
			'scale',
		];

		for (let key in rootData) {
			if (excludeKeys.indexOf(key) !== -1) {
				continue;
			}

			data[key] = rootData[key];
		}
	}

	_exportObjects(object, options) {
		if (!_filterObject(object, options)) {
			return null;
		}

		let _private = this[__.private];

		// Build object as JSON data
		let data = _private.sceneExporter.buildObject(object);

		// Continue to export children
		if (object.children.length) {
			let children = [];
			object.children.forEach(child => {
				let childData = this._exportObjects(child, options);
				if (childData) {
					children.push(childData);
				}
			});

			if (children.length) {
				data.children = children;
			}
		}

		return data;
	}

	// #endregion

	/**
	 * @typedef {Object} SceneObjectExporterOptions
	 * @property {String} rootPath The root path.
	 * @property {Boolean} includeSelf True indicates export self info, default is false.
	 * @property {Boolean} externalComponents Check whether export external components, default is true.
	 * @property {Boolean} lights Check whether export lights, default is false.
	 * @property {Boolean} camera Check whether export camera, default is false.
	 */

	/**
	 * Output JSON from specified object's children.
	 * @param {THING.BaseObject} root The root object.
	 * @param {SceneObjectExporterOptions} options The options.
	 * @returns {Object}
	 * @private
	 */
	output(root, options = {}) {
		let _private = this[__.private];

		// Get options
		let includeSelf = options['includeSelf'];

		// Initialize scene data
		let data = {};
		data['version'] = '1.0.0';
		data['id'] = MathUtils.generateUUID();

		// Export scene
		let sceneExporter = _private.sceneExporter;
		sceneExporter.begin(options);
		{
			// Collect self
			if (includeSelf) {
				sceneExporter.collectObject(root);
			}

			// Collect children
			root.children.traverse(object => {
				sceneExporter.collectObject(object);
			});

			// Export root
			if (includeSelf) {
				this._exportRootObject(data, root);
			}

			// Export objects.
			let objects = this._exportObjects(root, options);
			data['children'] = objects.children;

			// Get the resources
			data['resources'] = sceneExporter.getResources();
		}
		sceneExporter.end();

		return data;
	}

}

export { SceneObjectExporter }