Source: components/AppRenderConfigComponent.js

import { Utils } from '../common/Utils';
import { BaseComponent } from './BaseComponent';
import { DirectionalLight } from '../objects/DirectionalLight';
import { HemisphereLight } from '../objects/HemisphereLight';
import { AmbientLight } from '../objects/AmbientLight';

/**
 * @class AppRenderConfigComponent
 * The global renderSettings component.
 * @memberof THING
 * @extends THING.BaseComponent
 */
class AppRenderConfigComponent extends BaseComponent {

	/**
	 * The RenderSettings helper
	 */
	constructor() {
		super();
	}

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

	onRemove() {
		super.onRemove();
	}

	/**
	 * Configuration about app renderSettings.
	 * @typedef {Object} RenderSettingsInfo
	 * @property {background} background The camera's background.
	 * @property {environment} environment The scene's global environmentMap.
	 * @property {lights} light The lights config(lights under app.root.children).
	 * @property {postEffects} PostEffectInfo The camera postEffect info.
	 * @property {cameraEffects} cameraEffectInfo The camera effect info.
	 */

	/**
	 * Configuration about background
	 * @typedef {ImageTexture| CubeTexture | Array<Number>} background
	 */

	/**
	 * Configuration about environment
	 * @typedef {Object} environment
	 * @property {ImageTexture | CubeTexture} envMap The scene's envMap.
	 * @property {Number} diffuseIntensity The envMap light Intensity
	 */

	/**
	 * Configuration about lights
	 * @typedef {Object} lights
	 * @property {Array<AmbientLightInfo>} ambientLights The ambientLights config.
	 * @property {Array<DirectionalLightInfo>} directionalLights The directionalLights config.
	 * @property {Array<HemisphereLightInfo>} hemisphereLights The hemisphereLights config.
	 * @private
	 */

	/**
	 * Configuration about ambientLight
	 * @typedef {Object} AmbientLightInfo
	 * @property {Number} intensity The ambientLight intensity.
	 * @property {Array<Number>} color The ambientLight color.
	 * @property {String} uuid The ambientLight uuid.
	 * @property {Boolean} isMainLight Whether the ambientLight is main light.
	 * @private
	 */

	/**
	 * Configuration about directionalLight
	 * @typedef {Object} DirectionalLightInfo
	 * @property {Boolean} enableShadow Whether the directionalLight enable shadow.
	 * @property {Number} intensity The directionalLight intensity.
	 * @property {Array<Number>} color The directionalLight color.
	 * @property {Number} shadowBias The directionalLight shadow bias.
	 * @property {Number} shadowQuality The directionalLight shadow quality.
	 * @property {Number} horzAngle The directionalLight horizontal angles.
	 * @property {Number} vertAngle The directionalLight vertical angles.
	 * @property {Boolean} visible The directionalLight visible.
	 * @property {String} uuid The directionalLight uuid.
	 * @property {Boolean} isMainLight Whether the directionalLight is main light.
	 * @private
	 */

	/**
	 * Configuration about hemisphereLight
	 * @typedef {Object} HemisphereLightInfo
	 * @property {Number} intensity The hemisphereLight intensity.
	 * @property {Array<Number>} color The hemisphereLight color.
	 * @property {Array<Number>} groundColor The hemisphereLight ground color.
	 * @property {String} uuid The hemisphereLight uuid.
	 * @private
	 */

	/**
	 * get/set global renderSettings.(Can only control the lights under app.root.children)
	 * @type {RenderSettingsInfo}
	 */
	get renderSettings() {
		const app = this._object;

		const config = {
			'background': app.background,
			'environment': {
				'envMap': app.envMap,
				'diffuseIntensity': app.scene.envMapLightIntensity
			},
			'lights': {
				'ambientLights': [],
				'directionalLights': [],
				'hemisphereLights': []
			}
		};

		// fog
		config.fog = Utils.cloneObject(app.camera.fog.config, false);

		app.root.children.query('.AmbientLight').forEach(ambientLight => {
			const ambientLightConfig = {
				"intensity": ambientLight.intensity,
				"color": ambientLight.color
			};

			if (app.scene.ambientLight === ambientLight) {
				ambientLightConfig.isMainLight = true;
			}
			else {
				ambientLightConfig.uuid = ambientLight.uuid;
			}

			config.lights.ambientLights.push(ambientLightConfig)
		});

		app.root.children.query('.DirectionalLight').forEach(directionalLight => {
			const directionalLightConfig = {
				"enableShadow": directionalLight.enableShadow,
				"intensity": directionalLight.intensity,
				"color": directionalLight.color,
				"shadowBias": directionalLight.shadowBias,
				"shadowQuality": directionalLight.shadowQuality,
				"horzAngle": directionalLight.adapter.horzAngle,
				"vertAngle": directionalLight.adapter.vertAngle,
				"visible": directionalLight.visible
			};

			if (app.scene.mainLight === directionalLight) {
				directionalLightConfig.isMainLight = true;
			}
			else {
				directionalLightConfig.uuid = directionalLight.uuid;
			}

			config.lights.directionalLights.push(directionalLightConfig);
		});

		app.root.children.query('.HemisphereLight').forEach(hemisphereLight => {
			const hemisphereLightConfig = {
				'intensity': hemisphereLight.intensity,
				'color': hemisphereLight.color,
				'groundColor': hemisphereLight.groundColor,
				'uuid': hemisphereLight.uuid
			};

			config.lights.hemisphereLights.push(hemisphereLightConfig);
		});

		config.postEffects = Utils.cloneObject(app.camera.postEffect.config, false);
		config.cameraEffects = Utils.cloneObject(app.camera.effect.config, false);

		return config;
	}

	set renderSettings(config) {
		const app = this._object;

		app.root.children.query('.BaseLight').forEach(light => {
			light.destroy();
		});

		if (config.background) {
			if (!!app.background && (app.background.isImageTexture || app.background.isCubeTexture)) {
				app.background.release();
			}

			app.background = config.background;

			if (config.background.isImageTexture || app.background.isCubeTexture) {
				config.background.addRef();
			}
		}

		const environment = config.environment;
		if (environment) {
			if (environment.envMap) {
				if (!!app.envMap && (app.envMap.isImageTexture || app.envMap.isCubeTexture)) {
					app.envMap.release();
				}

				app.envMap = environment.envMap;

				if (environment.isImageTexture || environment.isCubeTexture) {
					environment.addRef();
				}
			}

			app.scene.envMapLightIntensity = environment.diffuseIntensity;
		}

		// fog

		const fog = config.fog;

		if (fog) {
			app.camera.fog.config = fog;
		}

		const lights = config.lights;

		const ambientLightConfigs = lights.ambientLights;

		ambientLightConfigs.forEach(ambientLightConfig => {
			let ambientLight;

			if (ambientLightConfig.isMainLight) {
				ambientLight = app.scene.ambientLight;
			}
			else {
				ambientLight = new AmbientLight();
			}

			for (let key in ambientLightConfig) {
				ambientLight[key] = ambientLightConfig[key];
			}
		})

		const directionalLightConfigs = lights.directionalLights;

		directionalLightConfigs.forEach(directionalLightConfig => {
			let directionalLight;

			if (directionalLightConfig.isMainLight) {
				directionalLight = app.scene.mainLight;
			}
			else {
				directionalLight = new DirectionalLight();
			}

			for (let key in directionalLightConfig) {
				if (key == 'adapter') {
					const adapterValue = directionalLightConfig[key];
					for (let _key in adapterValue) {
						directionalLight[key][_key] = adapterValue[_key];
					}
				}
				else if (key == 'helperVisible') {
					directionalLight.helper.visible = directionalLightConfig[key];
				}
				else if (key == 'horzAngle') {					// @compatible remove adapter
					const adapter = directionalLight.adapter;
					adapter.horzAngle = directionalLightConfig[key];
				}
				else if (key == 'vertAngle') {					// @compatible remove adapter
					const adapter = directionalLight.adapter;
					adapter.vertAngle = directionalLightConfig[key];
				}
				else {
					directionalLight[key] = directionalLightConfig[key];
				}
			}
		});

		const hemisphereLightConfigs = lights.hemisphereLights;
		hemisphereLightConfigs.forEach(hemisphereLightConfig => {
			const hemisphereLight = new HemisphereLight();
			for (let key in hemisphereLightConfig) {
				hemisphereLight[key] = hemisphereLightConfig[key];
			}
		});

		app.camera.postEffect.config = config.postEffects;
		app.camera.effect.config = config.cameraEffects;
	}

}

AppRenderConfigComponent.exportProperties = [
	'renderSettings'
];

export { AppRenderConfigComponent }