<commit_before>/**
 * @author Mugen87 / https://github.com/Mugen87
 */

THREE.SSAOPass = function ( scene, camera, width, height ) {

	THREE.Pass.call( this );

	this.width = ( width !== undefined ) ? width : 512;
	this.height = ( height !== undefined ) ? height : 512;

	this.clear = true;

	this.camera = camera;
	this.scene = scene;

	this.kernelRadius = 8;
	this.kernelSize = 64;
	this.kernel = [];
	this.noiseTexture = null;
	this.output = 0;

	this.minDistance = 0.005;
	this.maxDistance = 0.1;

	//

	this.generateSampleKernel();
	this.generateRandomKernelRotations();

	// beauty render target with depth buffer

	var depthTexture = new THREE.DepthTexture();
	depthTexture.type = THREE.UnsignedShortType;
	depthTexture.minFilter = THREE.NearestFilter;
	depthTexture.maxFilter = THREE.NearestFilter;

	this.beautyRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
		minFilter: THREE.LinearFilter,
		magFilter: THREE.LinearFilter,
		format: THREE.RGBAFormat,
		depthTexture: depthTexture,
		depthBuffer: true
	} );

	// normal render target

	this.normalRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
		minFilter: THREE.NearestFilter,
		magFilter: THREE.NearestFilter,
		format: THREE.RGBAFormat
	} );

	// ssao render target

	this.ssaoRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
		minFilter: THREE.LinearFilter,
		magFilter: THREE.LinearFilter,
		format: THREE.RGBAFormat
	} );

	this.blurRenderTarget = this.ssaoRenderTarget.clone();

	// ssao material

	if ( THREE.SSAOShader === undefined ) {

		console.error( 'THREE.SSAOPass: The pass relies on THREE.SSAOShader.' );

	}

	this.ssaoMaterial = new THREE.ShaderMaterial( {
		defines: Object.assign( {}, THREE.SSAOShader.defines ),
		uniforms: THREE.UniformsUtils.clone( THREE.SSAOShader.uniforms ),
		vertexShader: THREE.SSAOShader.vertexShader,
		fragmentShader: THREE.SSAOShader.fragmentShader,
		blending: THREE.NoBlending
	} );

	this.ssaoMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
	this.ssaoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
	this.ssaoMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
	this.ssaoMaterial.uniforms[ 'tNoise' ].value = this.noiseTexture;
	this.ssaoMaterial.uniforms[ 'kernel' ].value = this.kernel;
	this.ssaoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
	this.ssaoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
	this.ssaoMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
	this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
	this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.camera.projectionMatrix );

	// normal material

	this.normalMaterial = new THREE.MeshNormalMaterial();
	this.normalMaterial.blending = THREE.NoBlending;

	// blur material

	this.blurMaterial = new THREE.ShaderMaterial( {
		defines: Object.assign( {}, THREE.SSAOBlurShader.defines ),
		uniforms: THREE.UniformsUtils.clone( THREE.SSAOBlurShader.uniforms ),
		vertexShader: THREE.SSAOBlurShader.vertexShader,
		fragmentShader: THREE.SSAOBlurShader.fragmentShader
	} );
	this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
	this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );

	// material for rendering the depth

	this.depthRenderMaterial = new THREE.ShaderMaterial( {
		defines: Object.assign( {}, THREE.SSAODepthShader.defines ),
		uniforms: THREE.UniformsUtils.clone( THREE.SSAODepthShader.uniforms ),
		vertexShader: THREE.SSAODepthShader.vertexShader,
		fragmentShader: THREE.SSAODepthShader.fragmentShader,
		blending: THREE.NoBlending
	} );
	this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
	this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
	this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;

	// material for rendering the content of a render target

	this.copyMaterial = new THREE.ShaderMaterial( {
		uniforms: THREE.UniformsUtils.clone( THREE.CopyShader.uniforms ),
		vertexShader: THREE.CopyShader.vertexShader,
		fragmentShader: THREE.CopyShader.fragmentShader,
		transparent: true,
		depthTest: false,
		depthWrite: false,
		blendSrc: THREE.DstColorFactor,
		blendDst: THREE.ZeroFactor,
		blendEquation: THREE.AddEquation,
		blendSrcAlpha: THREE.DstAlphaFactor,
		blendDstAlpha: THREE.ZeroFactor,
		blendEquationAlpha: THREE.AddEquation
	} );

	//

	this.quadCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
	this.quadScene = new THREE.Scene();
	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
	this.quadScene.add( this.quad );

	//

	this.originalClearColor = new THREE.Color();

};

THREE.SSAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {

	constructor: THREE.SSAOPass,

	dispose: function () {

		// dispose render targets

		this.beautyRenderTarget.dispose();
		this.normalRenderTarget.dispose();
		this.ssaoRenderTarget.dispose();
		this.blurRenderTarget.dispose();

		// dispose geometry

		this.quad.geometry.dispose();

		// dispose materials

		this.normalMaterial.dispose();
		this.blurMaterial.dispose();
		this.copyMaterial.dispose();
		this.depthRenderMaterial.dispose();

	},

	render: function ( renderer, writeBuffer /*, readBuffer, delta, maskActive */ ) {

		// render beauty and depth

		renderer.render( this.scene, this.camera, this.beautyRenderTarget, true );

		// render normals

		this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );

		// render SSAO

		this.ssaoMaterial.uniforms[ 'kernelRadius' ].value = this.kernelRadius;
		this.ssaoMaterial.uniforms[ 'minDistance' ].value = this.minDistance;
		this.ssaoMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
		this.renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget );

		// render blur

		this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget );

		// output result to screen

		switch ( this.output ) {

			case THREE.SSAOPass.OUTPUT.SSAO:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Blur:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Beauty:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Depth:

				this.renderPass( renderer, this.depthRenderMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Normal:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Default:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
				this.copyMaterial.blending = THREE.CustomBlending;
				this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

				break;

			default:
				console.warn( 'THREE.SSAOPass: Unknown output type.' );

		}

	},

	renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {

		// save original state
		this.originalClearColor.copy( renderer.getClearColor() );
		var originalClearAlpha = renderer.getClearAlpha();
		var originalAutoClear = renderer.autoClear;

		// setup pass state
		renderer.autoClear = false;
		var clearNeeded = ( clearColor !== undefined ) && ( clearColor !== null );
		if ( clearNeeded ) {

			renderer.setClearColor( clearColor );
			renderer.setClearAlpha( clearAlpha || 0.0 );

		}

		this.quad.material = passMaterial;
		renderer.render( this.quadScene, this.quadCamera, renderTarget, clearNeeded );

		// restore original state
		renderer.autoClear = originalAutoClear;
		renderer.setClearColor( this.originalClearColor );
		renderer.setClearAlpha( originalClearAlpha );

	},

	renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {

		this.originalClearColor.copy( renderer.getClearColor() );
		var originalClearAlpha = renderer.getClearAlpha();
		var originalAutoClear = renderer.autoClear;

		renderer.autoClear = false;

		clearColor = overrideMaterial.clearColor || clearColor;
		clearAlpha = overrideMaterial.clearAlpha || clearAlpha;

		var clearNeeded = ( clearColor !== undefined ) && ( clearColor !== null );

		if ( clearNeeded ) {

			renderer.setClearColor( clearColor );
			renderer.setClearAlpha( clearAlpha || 0.0 );

		}

		this.scene.overrideMaterial = overrideMaterial;
		renderer.render( this.scene, this.camera, renderTarget, clearNeeded );
		this.scene.overrideMaterial = null;

		// restore original state

		renderer.autoClear = originalAutoClear;
		renderer.setClearColor( this.originalClearColor );
		renderer.setClearAlpha( originalClearAlpha );

	},

	setSize: function ( width, height ) {

		this.width = width;
		this.height = height;

		this.beautyRenderTarget.setSize( width, height );
		this.ssaoRenderTarget.setSize( width, height );
		this.normalRenderTarget.setSize( width, height );
		this.blurRenderTarget.setSize( width, height );

		this.ssaoMaterial.uniforms[ 'resolution' ].value.set( width, height );
		this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
		this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.camera.projectionMatrix );

		this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );

	},

	generateSampleKernel: function () {

		var kernelSize = this.kernelSize;
		var kernel = this.kernel;

		for ( var i = 0; i < kernelSize; i ++ ) {

			var sample = new THREE.Vector3();
			sample.x = ( Math.random() * 2 ) - 1;
			sample.y = ( Math.random() * 2 ) - 1;
			sample.z = Math.random();

			sample.normalize();

			var scale = i / kernelSize;
			scale = THREE.Math.lerp( 0.1, 1, scale * scale );
			sample.multiplyScalar( scale );

			kernel.push( sample );

		}

	},

	generateRandomKernelRotations: function () {

		var width = 4, height = 4;

		if ( SimplexNoise === undefined ) {

			console.error( 'THREE.SSAOPass: The pass relies on THREE.SimplexNoise.' );

		}

		var simplex = new SimplexNoise();

		var size = width * height;
		var data = new Float32Array( size );

		for ( var i = 0; i < size; i ++ ) {

			var x = ( Math.random() * 2 ) - 1;
			var y = ( Math.random() * 2 ) - 1;
			var z = 0;

			data[ i ] = simplex.noise3d( x, y, z );

		}

		this.noiseTexture = new THREE.DataTexture( data, width, height, THREE.LuminanceFormat, THREE.FloatType );
		this.noiseTexture.wrapS = THREE.RepeatWrapping;
		this.noiseTexture.wrapT = THREE.RepeatWrapping;
		this.noiseTexture.needsUpdate = true;

	}

} );

THREE.SSAOPass.OUTPUT = {
	'Default': 0,
	'SSAO': 1,
	'Blur': 2,
	'Beauty': 3,
	'Depth': 4,
	'Normal': 5
};
<commit_msg>Examples: Make SSAOPass WebGL 2 compatible.<commit_after>/**
 * @author Mugen87 / https://github.com/Mugen87
 */

THREE.SSAOPass = function ( scene, camera, width, height ) {

	THREE.Pass.call( this );

	this.width = ( width !== undefined ) ? width : 512;
	this.height = ( height !== undefined ) ? height : 512;

	this.clear = true;

	this.camera = camera;
	this.scene = scene;

	this.kernelRadius = 8;
	this.kernelSize = 64;
	this.kernel = [];
	this.noiseTexture = null;
	this.output = 0;

	this.minDistance = 0.005;
	this.maxDistance = 0.1;

	//

	this.generateSampleKernel();
	this.generateRandomKernelRotations();

	// beauty render target with depth buffer

	var depthTexture = new THREE.DepthTexture();
	depthTexture.type = THREE.UnsignedShortType;
	depthTexture.minFilter = THREE.NearestFilter;
	depthTexture.maxFilter = THREE.NearestFilter;

	this.beautyRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
		minFilter: THREE.LinearFilter,
		magFilter: THREE.LinearFilter,
		format: THREE.RGBAFormat,
		depthTexture: depthTexture,
		depthBuffer: true
	} );

	// normal render target

	this.normalRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
		minFilter: THREE.NearestFilter,
		magFilter: THREE.NearestFilter,
		format: THREE.RGBAFormat
	} );

	// ssao render target

	this.ssaoRenderTarget = new THREE.WebGLRenderTarget( this.width, this.height, {
		minFilter: THREE.LinearFilter,
		magFilter: THREE.LinearFilter,
		format: THREE.RGBAFormat
	} );

	this.blurRenderTarget = this.ssaoRenderTarget.clone();

	// ssao material

	if ( THREE.SSAOShader === undefined ) {

		console.error( 'THREE.SSAOPass: The pass relies on THREE.SSAOShader.' );

	}

	this.ssaoMaterial = new THREE.ShaderMaterial( {
		defines: Object.assign( {}, THREE.SSAOShader.defines ),
		uniforms: THREE.UniformsUtils.clone( THREE.SSAOShader.uniforms ),
		vertexShader: THREE.SSAOShader.vertexShader,
		fragmentShader: THREE.SSAOShader.fragmentShader,
		blending: THREE.NoBlending
	} );

	this.ssaoMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
	this.ssaoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
	this.ssaoMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
	this.ssaoMaterial.uniforms[ 'tNoise' ].value = this.noiseTexture;
	this.ssaoMaterial.uniforms[ 'kernel' ].value = this.kernel;
	this.ssaoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
	this.ssaoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
	this.ssaoMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
	this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
	this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.camera.projectionMatrix );

	// normal material

	this.normalMaterial = new THREE.MeshNormalMaterial();
	this.normalMaterial.blending = THREE.NoBlending;

	// blur material

	this.blurMaterial = new THREE.ShaderMaterial( {
		defines: Object.assign( {}, THREE.SSAOBlurShader.defines ),
		uniforms: THREE.UniformsUtils.clone( THREE.SSAOBlurShader.uniforms ),
		vertexShader: THREE.SSAOBlurShader.vertexShader,
		fragmentShader: THREE.SSAOBlurShader.fragmentShader
	} );
	this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
	this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );

	// material for rendering the depth

	this.depthRenderMaterial = new THREE.ShaderMaterial( {
		defines: Object.assign( {}, THREE.SSAODepthShader.defines ),
		uniforms: THREE.UniformsUtils.clone( THREE.SSAODepthShader.uniforms ),
		vertexShader: THREE.SSAODepthShader.vertexShader,
		fragmentShader: THREE.SSAODepthShader.fragmentShader,
		blending: THREE.NoBlending
	} );
	this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
	this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
	this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;

	// material for rendering the content of a render target

	this.copyMaterial = new THREE.ShaderMaterial( {
		uniforms: THREE.UniformsUtils.clone( THREE.CopyShader.uniforms ),
		vertexShader: THREE.CopyShader.vertexShader,
		fragmentShader: THREE.CopyShader.fragmentShader,
		transparent: true,
		depthTest: false,
		depthWrite: false,
		blendSrc: THREE.DstColorFactor,
		blendDst: THREE.ZeroFactor,
		blendEquation: THREE.AddEquation,
		blendSrcAlpha: THREE.DstAlphaFactor,
		blendDstAlpha: THREE.ZeroFactor,
		blendEquationAlpha: THREE.AddEquation
	} );

	//

	this.quadCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
	this.quadScene = new THREE.Scene();
	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
	this.quadScene.add( this.quad );

	//

	this.originalClearColor = new THREE.Color();

};

THREE.SSAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {

	constructor: THREE.SSAOPass,

	dispose: function () {

		// dispose render targets

		this.beautyRenderTarget.dispose();
		this.normalRenderTarget.dispose();
		this.ssaoRenderTarget.dispose();
		this.blurRenderTarget.dispose();

		// dispose geometry

		this.quad.geometry.dispose();

		// dispose materials

		this.normalMaterial.dispose();
		this.blurMaterial.dispose();
		this.copyMaterial.dispose();
		this.depthRenderMaterial.dispose();

	},

	render: function ( renderer, writeBuffer /*, readBuffer, delta, maskActive */ ) {

		// render beauty and depth

		renderer.render( this.scene, this.camera, this.beautyRenderTarget, true );

		// render normals

		this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );

		// render SSAO

		this.ssaoMaterial.uniforms[ 'kernelRadius' ].value = this.kernelRadius;
		this.ssaoMaterial.uniforms[ 'minDistance' ].value = this.minDistance;
		this.ssaoMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
		this.renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget );

		// render blur

		this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget );

		// output result to screen

		switch ( this.output ) {

			case THREE.SSAOPass.OUTPUT.SSAO:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Blur:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Beauty:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Depth:

				this.renderPass( renderer, this.depthRenderMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Normal:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				break;

			case THREE.SSAOPass.OUTPUT.Default:

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
				this.copyMaterial.blending = THREE.NoBlending;
				this.renderPass( renderer, this.copyMaterial, null );

				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
				this.copyMaterial.blending = THREE.CustomBlending;
				this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

				break;

			default:
				console.warn( 'THREE.SSAOPass: Unknown output type.' );

		}

	},

	renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {

		// save original state
		this.originalClearColor.copy( renderer.getClearColor() );
		var originalClearAlpha = renderer.getClearAlpha();
		var originalAutoClear = renderer.autoClear;

		// setup pass state
		renderer.autoClear = false;
		var clearNeeded = ( clearColor !== undefined ) && ( clearColor !== null );
		if ( clearNeeded ) {

			renderer.setClearColor( clearColor );
			renderer.setClearAlpha( clearAlpha || 0.0 );

		}

		this.quad.material = passMaterial;
		renderer.render( this.quadScene, this.quadCamera, renderTarget, clearNeeded );

		// restore original state
		renderer.autoClear = originalAutoClear;
		renderer.setClearColor( this.originalClearColor );
		renderer.setClearAlpha( originalClearAlpha );

	},

	renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {

		this.originalClearColor.copy( renderer.getClearColor() );
		var originalClearAlpha = renderer.getClearAlpha();
		var originalAutoClear = renderer.autoClear;

		renderer.autoClear = false;

		clearColor = overrideMaterial.clearColor || clearColor;
		clearAlpha = overrideMaterial.clearAlpha || clearAlpha;

		var clearNeeded = ( clearColor !== undefined ) && ( clearColor !== null );

		if ( clearNeeded ) {

			renderer.setClearColor( clearColor );
			renderer.setClearAlpha( clearAlpha || 0.0 );

		}

		this.scene.overrideMaterial = overrideMaterial;
		renderer.render( this.scene, this.camera, renderTarget, clearNeeded );
		this.scene.overrideMaterial = null;

		// restore original state

		renderer.autoClear = originalAutoClear;
		renderer.setClearColor( this.originalClearColor );
		renderer.setClearAlpha( originalClearAlpha );

	},

	setSize: function ( width, height ) {

		this.width = width;
		this.height = height;

		this.beautyRenderTarget.setSize( width, height );
		this.ssaoRenderTarget.setSize( width, height );
		this.normalRenderTarget.setSize( width, height );
		this.blurRenderTarget.setSize( width, height );

		this.ssaoMaterial.uniforms[ 'resolution' ].value.set( width, height );
		this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
		this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.camera.projectionMatrix );

		this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );

	},

	generateSampleKernel: function () {

		var kernelSize = this.kernelSize;
		var kernel = this.kernel;

		for ( var i = 0; i < kernelSize; i ++ ) {

			var sample = new THREE.Vector3();
			sample.x = ( Math.random() * 2 ) - 1;
			sample.y = ( Math.random() * 2 ) - 1;
			sample.z = Math.random();

			sample.normalize();

			var scale = i / kernelSize;
			scale = THREE.Math.lerp( 0.1, 1, scale * scale );
			sample.multiplyScalar( scale );

			kernel.push( sample );

		}

	},

	generateRandomKernelRotations: function () {

		var width = 4, height = 4;

		if ( SimplexNoise === undefined ) {

			console.error( 'THREE.SSAOPass: The pass relies on THREE.SimplexNoise.' );

		}

		var simplex = new SimplexNoise();

		var size = width * height;
		var data = new Float32Array( size * 4 );

		for ( var i = 0; i < size; i ++ ) {

			var stride = i * 4;

			var x = ( Math.random() * 2 ) - 1;
			var y = ( Math.random() * 2 ) - 1;
			var z = 0;

			var noise = simplex.noise3d( x, y, z );

			data[ stride ] = noise;
			data[ stride + 1 ] = noise;
			data[ stride + 2 ] = noise;
			data[ stride + 3 ] = 1;

		}

		this.noiseTexture = new THREE.DataTexture( data, width, height, THREE.RGBA, THREE.FloatType );
		this.noiseTexture.wrapS = THREE.RepeatWrapping;
		this.noiseTexture.wrapT = THREE.RepeatWrapping;
		this.noiseTexture.needsUpdate = true;

	}

} );

THREE.SSAOPass.OUTPUT = {
	'Default': 0,
	'SSAO': 1,
	'Blur': 2,
	'Beauty': 3,
	'Depth': 4,
	'Normal': 5
};
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var harness = require('./harness.js');

describe('#cluster management', function() {
  function allTests(H) {
    it('should be able to access a cluster manager', function () {
      var cluster = new H.lib.Cluster(H.connstr);
      var clusterMgr = cluster.manager('Administrator', 'C0uchbase');
      assert(clusterMgr);
    });

    it('should be able to list buckets', function () {
      var cluster = new H.lib.Cluster(H.connstr);
      var clusterMgr = cluster.manager('Administrator', 'C0uchbase');
      clusterMgr.listBuckets(function (err, list) {
        assert(!err);
        assert(list);
      });
    });
  }
  describe('#RealBucket', allTests.bind(this, harness));
  describe('#MockBucket', allTests.bind(this, harness.mock));
});
<commit_msg>use credentials from harness instead of hard-coded values<commit_after>'use strict';

var assert = require('assert');
var harness = require('./harness.js');

describe('#cluster management', function() {
  function allTests(H) {
    it('should be able to access a cluster manager', function () {
      var cluster = new H.lib.Cluster(H.connstr);
      var clusterMgr = cluster.manager(H.muser, H.mpass);
      assert(clusterMgr);
    });

    it('should be able to list buckets', function () {
      var cluster = new H.lib.Cluster(H.connstr);
      var clusterMgr = cluster.manager(H.muser, H.mpass);
      clusterMgr.listBuckets(function (err, list) {
        assert(!err);
        assert(list);
      });
    });
  }
  describe('#RealBucket', allTests.bind(this, harness));
  describe('#MockBucket', allTests.bind(this, harness.mock));
});
<|endoftext|>


<commit_before>// This file sets a global base for themes
// Not required but recommended for any functionality

/**
 * Major dependencies
 */

	// Node
var path = require('path'),
	fs = require('fs'),
	crypto = require('crypto'),

	// JS Extensions
	_ = require('underscore'),
	sugar = require('sugar'),

	// Specific
	promise = require('fibers-promise'),
	Asset = require('./asset'),
	util = require('./utility');

var theme_setup = function() {

	/*
	 * Theme file extensions and prefilters
	 */

	// HTML, Text, Images; Don't need a filter fnc because they don't process anything
	this.register_asset_type("html", [ "html", "htm" ]);
	this.register_asset_type("text", "txt");
	this.register_asset_type("image", [ "png", "gif", "jpg", "jpeg" ]);
	this.register_asset_type("font", [ "ttf", "woff", "eot" ]);
	this.register_asset_type("svg", "svg");

	// Handlebar
	var Handlebars = require('handlebars');
	this.register_asset_type("handlebar", [ "handlebar", "hbr" ], function(asset) {
		// Precompile the handlebar template
		var content = Handlebars.compile(asset.toString());

		// Let's reconstruct this asset
		asset.type = "html";
		asset.name += ".html";

		// This function is not defined by the traditional asset set up
		// It will still attempt to be called during compile regardless
		asset.compile = content;

		return asset;
	});

	this.register_asset_type("css", "css", function(asset) {
		// Determine if we should minify; First check the asset options
		var minify = _.isBoolean(asset.options.minify) ? asset.options.minify : false;
		if (!minify && _.isBoolean(this.options.minify)) minify = this.options.minify; // Otherwise load normal options

		// Minify the css with Sqwish
		if (minify === true) asset.write(util.minify_css(asset));

		return asset;
	});

	this.register_asset_type("javascript", "js", function(asset) {
		// Determine if we should minify; First check the asset options
		var minify = _.isBoolean(asset.options.minify) ? asset.options.minify : false;
		if (!minify && _.isBoolean(this.options.minify)) minify = this.options.minify; // Otherwise load normal options

		// Minify the js with Uglify
		if (minify === true) asset.write(util.minify_js(asset));

		return asset;
	});

	// Less
	var less = require('less');
	this.register_asset_type("less", "less", function(asset) {
		var p = promise.t(),
			parser = new(less.Parser)({
				paths: [path.dirname(asset.file)], // Specify search paths for @import directives
				filename: asset.name
			}),
			content = asset.toString(), css;

		// Determine if we should minify; First check the asset options
		var minify = _.isBoolean(asset.options.minify) ? asset.options.minify : false;
		if (!minify && _.isBoolean(this.options.minify)) minify = this.options.minify; // Otherwise load normal options

		// Render the less
		parser.parse(content, p);
		css = p.get().toCSS({ compress: minify });

		// Let's reconstruct this asset
		asset.type = "css";
		asset.name += ".css";
		asset.write(css);

		return asset;
	});

	/*
	 * Theme compile strategies
	 */

	// Content (mainly HTML)
	this.register_strategy("content", function(assets, options) {

		switch(this.state) {
			case "preparing":
				// In precompilation do nothing
				return assets;
				break;

			case "ready":
				// Check for context
				if (!_.isObject(options.context)) options.context = {};

				// Create a new blank asset
				var nasset = new Asset({
					name: "content",
					type: "html"
				});

				// During compilation, get context, render
				return [ _.reduce(assets, function(memo, asset) {
					var content = "";

					// Wrap this asset into the context
					var context = _.extend({}, options.context, {
						_asset: asset.toObject("content")
					})

					// Test asset for a compile function and run, otherwise get the content normally
					if (_.isFunction(asset.compile)) content = asset.compile.call(asset, context);
					else content = asset.toString();

					// Append the asset
					memo.append(content);
					return memo;
				}, nasset) ];

				break;
		}

	});

	// Scripts (mainly JS)
	this.register_strategy("scripts", function(assets, options) {

		// Setup options
		_.defaults(options, {
			concat: this.options.concat || false
		});

		switch(this.state) {
			case "preparing":
				// In precompilation we should do a non-destructive concatenation
				return options.concat ? util.concat(assets) : assets;
				break;

			case "ready":
				// During compilation, there shouldn't be anything to do
				return assets;
		}

	});

	// Styles (mainly CSS)
	this.register_strategy("styles", function(assets, options) {

		// Setup options
		_.defaults(options, {
			concat: this.options.concat || false
		});

		switch(this.state) {
			case "preparing":
				// In precompilation we should do a non-destructive concatenation
				return options.concat ? util.concat(assets) : assets;
				break;

			case "ready":
				// During compilation, there shouldn't be anything to do
				return assets;
		}

	});

	// Misc Headers
	this.register_strategy("headers", function(assets, options) {

		// Setup options
		_.defaults(options, {
			concat: this.options.concat || false
		});

		switch(this.state) {
			case "preparing":
				// In precompilation we should do a non-destructive concatenation
				return options.concat ? util.concat(assets) : assets;
				break;

			case "ready":
				// During compilation we should do a destructive concatenation (ie. everything should become one file regardless)
				var nasset = new Asset({
					name: "headers",
					type: "text"
				});

				return [ _.reduce(assets, function(memo, asset) {
					memo.append(asset.toString());
					return memo;
				}, nasset) ];

				break;
		}

	});

	/*
	 * Theme actions
	 */

	this.register_action("precompile", function(options) {
		// Set the state
		this.change_states("preparing");

		// Parse options
		options = this.parse_options(options);

		// Simple, loop through asset groups and execute their strategy.
		_.each(this.asset_groups, _.bind(function(data, group) {
			var opts = _.has(options, group) ? options[group] : {},
				assets = data.assets,
				nassets = this.execute(group, opts);

			// During precompile, assets are overwritten by the strategy return.
			// To prevent cache memory leak, this must loop through the current assets
			// and destroy anything that isn't in the new assets.
			_.each(assets, function(asset) {
				// Search for the asset in the current assets
				if (_.indexOf(nassets, asset) === -1) {
					// Destroy it
					asset.destroy();
				}
			});

			// Reset the assets array for the group and add all of the new assets
			this.remove_assets(group);
			this.add_asset(group, nassets);
		}, this));

		// Set the state
		this.change_states("ready");
	});

	// Turn a layout into some HTML
	this.register_action("compile", function(options) {
		// We don't set the state for caching reasons

		var parts = [ "styles", "scripts", "headers" ],
			rendered = {},
			context, content, compiled;

		// Parse options
		options = this.parse_options(options);

		// First compile the misc parts
		_.each(parts, _.bind(function(part) {
			var opts = _.has(options, part) ? options[part] : {};

			rendered[part] = this.execute(part, opts);
		}, this));

		// Set context if isn't already
		context = options.content.context;
		if (!_.isObject(context)) context = {};

		// Headers
		context.headers = _.size(rendered.headers) ? rendered.headers[0].toString() : "";

		// Styles
		context.styles = _.size(rendered.styles) ? util.asset_html(rendered.styles, {
			src_format: "<link rel=\"stylesheet\" href=\"{src}\" type=\"text/css\"/>\n",
			public_url: _.isFunction(this.public_url) ? this.public_url : null
		}) : "";

		// Scripts
		context.scripts = _.size(rendered.scripts) ? util.asset_html(rendered.scripts, {
			src_format: "<script src=\"{src}\" type=\"text/javascript\"></script>\n",
			public_url: _.isFunction(this.public_url) ? this.public_url : null
		}) : "";

		// Reset the context JIC
		options.content.context = context;

		// Compile
		content = this.execute("content", options.content);
		compiled = _.size(content) ? content[0].toString() : "";

		// Collect garbage
		_.invoke(rendered.headers, "destroy");
		_.invoke(content, "destroy");

		// Return
		return compiled;
	});

	/*
	 * Theme global assets
	 */

	/*// Load the file
	var globals = JSON.parse(fs.readFileSync(path.resolve(__dirname, "./assets/globals.json")));

	// Loop through json file
	_.each(globals, _.bind(function(item, id) {
		// Process the item as an asset
		var asset = this.new_asset(item, path.resolve(__dirname, "assets"));

		// Add it to the theme
		this.add_global_asset(id, asset);
	}, this));*/
}

// Bind and execute
module.exports = function(Theme) {
	_.bind(theme_setup, Theme)();
};<commit_msg>cleaned up setup<commit_after>// This file sets a global base for themes
// Not required but recommended for any functionality

/**
 * Major dependencies
 */

	// Node
var path = require('path'),
	fs = require('fs'),
	crypto = require('crypto'),

	// JS Extensions
	_ = require('underscore'),
	sugar = require('sugar'),

	// Specific
	promise = require('fibers-promise'),
	Asset = require('./asset'),
	util = require('./utility');

var theme_setup = function() {

	/*
	 * Theme file extensions and prefilters
	 */

	// HTML, Text, Images; Don't need a filter fnc because they don't process anything
	this.register_asset_type("html", [ "html", "htm" ]);
	this.register_asset_type("text", "txt");
	this.register_asset_type("image", [ "png", "gif", "jpg", "jpeg" ]);
	this.register_asset_type("font", [ "ttf", "woff", "eot" ]);
	this.register_asset_type("svg", "svg");

	// Handlebar
	var Handlebars = require('handlebars');
	this.register_asset_type("handlebar", [ "handlebar", "hbr" ], function(asset) {
		// Precompile the handlebar template
		var content = Handlebars.compile(asset.toString());

		// Let's reconstruct this asset
		asset.type = "html";
		asset.name += ".html";

		// This function is not defined by the traditional asset set up
		// It will still attempt to be called during compile regardless
		asset.compile = content;

		return asset;
	});

	this.register_asset_type("css", "css", function(asset) {
		// Determine if we should minify; First check the asset options
		var minify = _.isBoolean(asset.options.minify) ? asset.options.minify : false;
		if (!minify && _.isBoolean(this.options.minify)) minify = this.options.minify; // Otherwise load normal options

		// Minify the css with Sqwish
		if (minify === true) asset.write(util.minify_css(asset));

		return asset;
	});

	this.register_asset_type("javascript", "js", function(asset) {
		// Determine if we should minify; First check the asset options
		var minify = _.isBoolean(asset.options.minify) ? asset.options.minify : false;
		if (!minify && _.isBoolean(this.options.minify)) minify = this.options.minify; // Otherwise load normal options

		// Minify the js with Uglify
		if (minify === true) asset.write(util.minify_js(asset));

		return asset;
	});

	// Less
	var less = require('less');
	this.register_asset_type("less", "less", function(asset) {
		var p = promise.t(),
			parser = new(less.Parser)({
				paths: [path.dirname(asset.file)], // Specify search paths for @import directives
				filename: asset.name
			}),
			content = asset.toString(), css;

		// Determine if we should minify; First check the asset options
		var minify = _.isBoolean(asset.options.minify) ? asset.options.minify : false;
		if (!minify && _.isBoolean(this.options.minify)) minify = this.options.minify; // Otherwise load normal options

		// Render the less
		parser.parse(content, p);
		css = p.get().toCSS({ compress: minify });

		// Let's reconstruct this asset
		asset.type = "css";
		asset.name += ".css";
		asset.write(css);

		return asset;
	});

	/*
	 * Theme compile strategies
	 */

	// Content (mainly HTML)
	this.register_strategy("content", function(assets, options) {

		switch(this.state) {
			case "preparing":
				// In precompilation do nothing
				return assets;
				break;

			case "ready":
				// Check for context
				if (!_.isObject(options.context)) options.context = {};

				// Create a new blank asset
				var nasset = new Asset({
					name: "content",
					type: "html"
				});

				// During compilation, get context, render
				return [ _.reduce(assets, function(memo, asset) {
					var content = "";

					// Wrap this asset into the context
					var context = _.extend({}, options.context, {
						_asset: asset.toObject("content")
					})

					// Test asset for a compile function and run, otherwise get the content normally
					if (_.isFunction(asset.compile)) content = asset.compile.call(asset, context);
					else content = asset.toString();

					// Append the asset
					memo.append(content);
					return memo;
				}, nasset) ];

				break;
		}

	});

	// Scripts (mainly JS)
	this.register_strategy("scripts", function(assets, options) {

		// Setup options
		_.defaults(options, {
			concat: this.options.concat || false
		});

		switch(this.state) {
			case "preparing":
				// In precompilation we should do a non-destructive concatenation
				return options.concat ? util.concat(assets) : assets;
				break;

			case "ready":
				// During compilation, there shouldn't be anything to do
				return assets;
		}

	});

	// Styles (mainly CSS)
	this.register_strategy("styles", function(assets, options) {

		// Setup options
		_.defaults(options, {
			concat: this.options.concat || false
		});

		switch(this.state) {
			case "preparing":
				// In precompilation we should do a non-destructive concatenation
				return options.concat ? util.concat(assets) : assets;
				break;

			case "ready":
				// During compilation, there shouldn't be anything to do
				return assets;
		}

	});

	// Misc Headers
	this.register_strategy("headers", function(assets, options) {

		// Setup options
		_.defaults(options, {
			concat: this.options.concat || false
		});

		switch(this.state) {
			case "preparing":
				// In precompilation we should do a non-destructive concatenation
				return options.concat ? util.concat(assets) : assets;
				break;

			case "ready":
				// During compilation we should do a destructive concatenation (ie. everything should become one file regardless)
				var nasset = new Asset({
					name: "headers",
					type: "text"
				});

				return [ _.reduce(assets, function(memo, asset) {
					memo.append(asset.toString());
					return memo;
				}, nasset) ];

				break;
		}

	});

	/*
	 * Theme actions
	 */

	this.register_action("precompile", function(options) {
		// Set the state
		this.change_states("preparing");

		// Parse options
		options = this.parse_options(options);

		// Simple, loop through asset groups and execute their strategy.
		_.each(this.asset_groups, _.bind(function(data, group) {
			var opts = _.has(options, group) ? options[group] : {},
				assets = data.assets,
				nassets = this.execute(group, opts);

			// During precompile, assets are overwritten by the strategy return.
			// To prevent cache memory leak, this must loop through the current assets
			// and destroy anything that isn't in the new assets.
			_.each(assets, function(asset) {
				// Search for the asset in the current assets
				if (_.indexOf(nassets, asset) === -1) {
					// Destroy it
					asset.destroy();
				}
			});

			// Reset the assets array for the group and add all of the new assets
			this.remove_assets(group);
			this.add_asset(group, nassets);
		}, this));

		// Set the state
		this.change_states("ready");
	});

	// Turn a layout into some HTML
	this.register_action("compile", function(options) {
		// We don't set the state for caching reasons

		var parts = [ "styles", "scripts", "headers" ],
			rendered = {},
			context, content, compiled;

		// Parse options
		options = this.parse_options(options);

		// First compile the misc parts
		_.each(parts, _.bind(function(part) {
			var opts = _.has(options, part) ? options[part] : {};

			rendered[part] = this.execute(part, opts);
		}, this));

		// Set context if isn't already
		context = options.content.context;
		if (!_.isObject(context)) context = {};

		// Headers
		context.headers = _.size(rendered.headers) ? rendered.headers[0].toString() : "";

		// Styles
		context.styles = _.size(rendered.styles) ? util.asset_html(rendered.styles, {
			src_format: "<link rel=\"stylesheet\" href=\"{src}\" type=\"text/css\"/>\n",
			public_url: _.isFunction(this.public_url) ? this.public_url : null
		}) : "";

		// Scripts
		context.scripts = _.size(rendered.scripts) ? util.asset_html(rendered.scripts, {
			src_format: "<script src=\"{src}\" type=\"text/javascript\"></script>\n",
			public_url: _.isFunction(this.public_url) ? this.public_url : null
		}) : "";

		// Reset the context JIC
		options.content.context = context;

		// Compile
		content = this.execute("content", options.content);
		compiled = _.size(content) ? content[0].toString() : "";

		// Collect garbage
		_.invoke(rendered.headers, "destroy");
		_.invoke(content, "destroy");

		// Return
		return compiled;
	});
}

// Bind and execute
module.exports = function(Theme) {
	_.bind(theme_setup, Theme)();
};<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.CSS2DObject = function ( element ) {

	THREE.Object3D.call( this );

	this.element = element;
	this.element.style.position = 'absolute';

	this.addEventListener( 'removed', function () {

		this.traverse( function ( object ) {

			if ( object.element instanceof Element && object.element.parentNode !== null ) {

				object.element.parentNode.removeChild( object.element );

			}

		} );

	} );

};

THREE.CSS2DObject.prototype = Object.create( THREE.Object3D.prototype );
THREE.CSS2DObject.prototype.constructor = THREE.CSS2DObject;

//

THREE.CSS2DRenderer = function () {

	var _width, _height;
	var _widthHalf, _heightHalf;

	var vector = new THREE.Vector3();
	var viewMatrix = new THREE.Matrix4();
	var viewProjectionMatrix = new THREE.Matrix4();

	var cache = {
		objects: new WeakMap()
	};

	var domElement = document.createElement( 'div' );
	domElement.style.overflow = 'hidden';

	this.domElement = domElement;

	this.getSize = function () {

		return {
			width: _width,
			height: _height
		};

	};

	this.setSize = function ( width, height ) {

		_width = width;
		_height = height;

		_widthHalf = _width / 2;
		_heightHalf = _height / 2;

		domElement.style.width = width + 'px';
		domElement.style.height = height + 'px';

	};

	var renderObject = function ( object, camera ) {

		if ( object instanceof THREE.CSS2DObject ) {

			vector.setFromMatrixPosition( object.matrixWorld );
			vector.applyMatrix4( viewProjectionMatrix );

			var element = object.element;
			var style = 'translate(-50%,-50%) translate(' + ( vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - vector.y * _heightHalf + _heightHalf ) + 'px)';

			element.style.WebkitTransform = style;
			element.style.MozTransform = style;
			element.style.oTransform = style;
			element.style.transform = style;

			element.style.display = ( object.visible && vector.z >= - 1 && vector.z <= 1 ) ? '' : 'none';

			var objectData = {
				distanceToCameraSquared: getDistanceToSquared( camera, object )
			};

			cache.objects.set( object, objectData );

			if ( element.parentNode !== domElement ) {

				domElement.appendChild( element );

			}

		}

		for ( var i = 0, l = object.children.length; i < l; i ++ ) {

			renderObject( object.children[ i ], camera );

		}

	};

	var getDistanceToSquared = function () {

		var a = new THREE.Vector3();
		var b = new THREE.Vector3();

		return function ( object1, object2 ) {

			a.setFromMatrixPosition( object1.matrixWorld );
			b.setFromMatrixPosition( object2.matrixWorld );

			return a.distanceToSquared( b );

		};

	}();

	var filterAndFlatten = function ( scene ) {

		var result = [];

		scene.traverse( function ( object ) {

			if ( object instanceof THREE.CSS2DObject ) result.push( object );

		} );

		return result;

	};

	var zOrder = function ( scene ) {

		var sorted = filterAndFlatten( scene ).sort( function ( a, b ) {

			var distanceA = cache.objects.get( a ).distanceToCameraSquared;
			var distanceB = cache.objects.get( b ).distanceToCameraSquared;

			return distanceA - distanceB;

		} );

		var zMax = sorted.length;

		for ( var i = 0, l = sorted.length; i < l; i ++ ) {

			sorted[ i ].element.style.zIndex = zMax - i;

		}

	};

	this.render = function ( scene, camera ) {

		if (scene.autoUpdate === true) { scene.updateMatrixWorld(); }

		if ( camera.parent === null ) camera.updateMatrixWorld();

		viewMatrix.copy( camera.matrixWorldInverse );
		viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, viewMatrix );

		renderObject( scene, camera );
		zOrder( scene );

	};

};
<commit_msg>Update CSS2DRenderer.js<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.CSS2DObject = function ( element ) {

	THREE.Object3D.call( this );

	this.element = element;
	this.element.style.position = 'absolute';

	this.addEventListener( 'removed', function () {

		this.traverse( function ( object ) {

			if ( object.element instanceof Element && object.element.parentNode !== null ) {

				object.element.parentNode.removeChild( object.element );

			}

		} );

	} );

};

THREE.CSS2DObject.prototype = Object.create( THREE.Object3D.prototype );
THREE.CSS2DObject.prototype.constructor = THREE.CSS2DObject;

//

THREE.CSS2DRenderer = function () {

	var _width, _height;
	var _widthHalf, _heightHalf;

	var vector = new THREE.Vector3();
	var viewMatrix = new THREE.Matrix4();
	var viewProjectionMatrix = new THREE.Matrix4();

	var cache = {
		objects: new WeakMap()
	};

	var domElement = document.createElement( 'div' );
	domElement.style.overflow = 'hidden';

	this.domElement = domElement;

	this.getSize = function () {

		return {
			width: _width,
			height: _height
		};

	};

	this.setSize = function ( width, height ) {

		_width = width;
		_height = height;

		_widthHalf = _width / 2;
		_heightHalf = _height / 2;

		domElement.style.width = width + 'px';
		domElement.style.height = height + 'px';

	};

	var renderObject = function ( object, camera ) {

		if ( object instanceof THREE.CSS2DObject ) {

			vector.setFromMatrixPosition( object.matrixWorld );
			vector.applyMatrix4( viewProjectionMatrix );

			var element = object.element;
			var style = 'translate(-50%,-50%) translate(' + ( vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - vector.y * _heightHalf + _heightHalf ) + 'px)';

			element.style.WebkitTransform = style;
			element.style.MozTransform = style;
			element.style.oTransform = style;
			element.style.transform = style;

			element.style.display = ( object.visible && vector.z >= - 1 && vector.z <= 1 ) ? '' : 'none';

			var objectData = {
				distanceToCameraSquared: getDistanceToSquared( camera, object )
			};

			cache.objects.set( object, objectData );

			if ( element.parentNode !== domElement ) {

				domElement.appendChild( element );

			}

		}

		for ( var i = 0, l = object.children.length; i < l; i ++ ) {

			renderObject( object.children[ i ], camera );

		}

	};

	var getDistanceToSquared = function () {

		var a = new THREE.Vector3();
		var b = new THREE.Vector3();

		return function ( object1, object2 ) {

			a.setFromMatrixPosition( object1.matrixWorld );
			b.setFromMatrixPosition( object2.matrixWorld );

			return a.distanceToSquared( b );

		};

	}();

	var filterAndFlatten = function ( scene ) {

		var result = [];

		scene.traverse( function ( object ) {

			if ( object instanceof THREE.CSS2DObject ) result.push( object );

		} );

		return result;

	};

	var zOrder = function ( scene ) {

		var sorted = filterAndFlatten( scene ).sort( function ( a, b ) {

			var distanceA = cache.objects.get( a ).distanceToCameraSquared;
			var distanceB = cache.objects.get( b ).distanceToCameraSquared;

			return distanceA - distanceB;

		} );

		var zMax = sorted.length;

		for ( var i = 0, l = sorted.length; i < l; i ++ ) {

			sorted[ i ].element.style.zIndex = zMax - i;

		}

	};

	this.render = function ( scene, camera ) {

		if ( scene.autoUpdate === true ) { scene.updateMatrixWorld(); }

		if ( camera.parent === null ) camera.updateMatrixWorld();

		viewMatrix.copy( camera.matrixWorldInverse );
		viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, viewMatrix );

		renderObject( scene, camera );
		zOrder( scene );

	};

};
<|endoftext|>


<commit_before><commit_msg>Changed npl4.mpa.se to npl.mpa.se. Added a flag to accept unleafy certificates. Issue to npl.mpa.se sent.<commit_after><|endoftext|>


<commit_before>import extend from 'extend';
import Delta from 'quill-delta';
import Emitter from '../core/emitter';
import Keyboard from '../modules/keyboard';
import Theme from '../core/theme';
import ColorPicker from '../ui/color-picker';
import IconPicker from '../ui/icon-picker';
import Picker from '../ui/picker';
import Tooltip from '../ui/tooltip';

const ALIGNS = [ false, 'center', 'right', 'justify' ];

const COLORS = [
  "#000000", "#e60000", "#ff9900", "#ffff00", "#008a00", "#0066cc", "#9933ff",
  "#ffffff", "#facccc", "#ffebcc", "#ffffcc", "#cce8cc", "#cce0f5", "#ebd6ff",
  "#bbbbbb", "#f06666", "#ffc266", "#ffff66", "#66b966", "#66a3e0", "#c285ff",
  "#888888", "#a10000", "#b26b00", "#b2b200", "#006100", "#0047b2", "#6b24b2",
  "#444444", "#5c0000", "#663d00", "#666600", "#003700", "#002966", "#3d1466"
];

const FONTS = [ false, 'serif', 'monospace' ];

const HEADERS = [ '1', '2', '3', false ];

const SIZES = [ 'small', false, 'large', 'huge' ];

class BaseTheme extends Theme {
  constructor(quill, options) {
    super(quill, options);
    let listener = (e) => {
      if (!document.body.contains(quill.root)) {
        return document.body.removeEventListener('click', listener);
      }
      if (this.tooltip != null && !this.tooltip.root.contains(e.target) &&
          document.activeElement !== this.tooltip.textbox && !this.quill.hasFocus()) {
        this.tooltip.hide();
      }
      if (this.pickers != null) {
        this.pickers.forEach(function(picker) {
          if (!picker.container.contains(e.target)) {
            picker.close();
          }
        });
      }
    };
    document.body.addEventListener('click', listener);
  }

  addModule(name) {
    let module = super.addModule(name);
    if (name === 'toolbar') {
      this.extendToolbar(module);
    }
    return module;
  }

  buildButtons(buttons, icons) {
    buttons.forEach((button) => {
      let className = button.getAttribute('class') || '';
      className.split(/\s+/).forEach((name) => {
        if (!name.startsWith('ql-')) return;
        name = name.slice('ql-'.length);
        if (icons[name] == null) return;
        if (name === 'direction') {
          button.innerHTML = icons[name][''] + icons[name]['rtl'];
        } else if (typeof icons[name] === 'string') {
          button.innerHTML = icons[name];
        } else {
          let value = button.value || '';
          if (value != null && icons[name][value]) {
            button.innerHTML = icons[name][value];
          }
        }
      });
    });
  }

  buildPickers(selects, icons) {
    this.pickers = selects.map((select) => {
      if (select.classList.contains('ql-align')) {
        if (select.querySelector('option') == null) {
          fillSelect(select, ALIGNS);
        }
        return new IconPicker(select, icons.align);
      } else if (select.classList.contains('ql-background') || select.classList.contains('ql-color')) {
        let format = select.classList.contains('ql-background') ? 'background' : 'color';
        if (select.querySelector('option') == null) {
          fillSelect(select, COLORS, format === 'background' ? '#ffffff' : '#000000');
        }
        return new ColorPicker(select, icons[format]);
      } else {
        if (select.querySelector('option') == null) {
          if (select.classList.contains('ql-font')) {
            fillSelect(select, FONTS);
          } else if (select.classList.contains('ql-header')) {
            fillSelect(select, HEADERS);
          } else if (select.classList.contains('ql-size')) {
            fillSelect(select, SIZES);
          }
        }
        return new Picker(select);
      }
    });
    let update = () => {
      this.pickers.forEach(function(picker) {
        picker.update();
      });
    };
    this.quill.on(Emitter.events.EDITOR_CHANGE, update);
  }
}
BaseTheme.DEFAULTS = extend(true, {}, Theme.DEFAULTS, {
  modules: {
    toolbar: {
      handlers: {
        formula: function() {
          this.quill.theme.tooltip.edit('formula');
        },
        image: function() {
          let fileInput = this.container.querySelector('input.ql-image[type=file]');
          if (fileInput == null) {
            fileInput = document.createElement('input');
            fileInput.setAttribute('type', 'file');
            fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon');
            fileInput.classList.add('ql-image');
            fileInput.addEventListener('change', () => {
              if (fileInput.files != null && fileInput.files[0] != null) {
                let reader = new FileReader();
                reader.onload = (e) => {
                  let range = this.quill.getSelection(true);
                  this.quill.updateContents(new Delta()
                    .retain(range.index)
                    .delete(range.length)
                    .insert({ image: e.target.result })
                  , Emitter.sources.USER);
                  fileInput.value = "";
                }
                reader.readAsDataURL(fileInput.files[0]);
              }
            });
            this.container.appendChild(fileInput);
          }
          fileInput.click();
        },
        video: function() {
          this.quill.theme.tooltip.edit('video');
        }
      }
    }
  }
});

class BaseTooltip extends Tooltip {
  constructor(quill, boundsContainer) {
    super(quill, boundsContainer);
    this.textbox = this.root.querySelector('input[type="text"]');
    this.listen();
  }

  listen() {
    this.textbox.addEventListener('keydown', (event) => {
      if (Keyboard.match(event, 'enter')) {
        this.save();
        event.preventDefault();
      } else if (Keyboard.match(event, 'escape')) {
        this.cancel();
        event.preventDefault();
      }
    });
  }

  cancel() {
    this.hide();
  }

  edit(mode = 'link', preview = null) {
    this.root.classList.remove('ql-hidden');
    this.root.classList.add('ql-editing');
    if (preview != null) {
      this.textbox.value = preview;
    } else if (mode !== this.root.getAttribute('data-mode')) {
      this.textbox.value = '';
    }
    this.position(this.quill.getBounds(this.quill.selection.savedRange));
    this.textbox.select();
    this.textbox.setAttribute('placeholder', this.textbox.getAttribute(`data-${mode}`) || '');
    this.root.setAttribute('data-mode', mode);
  }

  restoreFocus() {
    let scrollTop = this.quill.scrollingContainer.scrollTop;
    this.quill.focus();
    this.quill.scrollingContainer.scrollTop = scrollTop;
  }

  save() {
    let value = this.textbox.value;
    switch(this.root.getAttribute('data-mode')) {
      case 'link': {
        let scrollTop = this.quill.root.scrollTop;
        if (this.linkRange) {
          this.quill.formatText(this.linkRange, 'link', value, Emitter.sources.USER);
          delete this.linkRange;
        } else {
          this.restoreFocus();
          this.quill.format('link', value, Emitter.sources.USER);
        }
        this.quill.root.scrollTop = scrollTop;
        break;
      }
      case 'video': {
        value = extractVideoUrl(value);
      } // eslint-disable-next-line no-fallthrough
      case 'formula': {
        if (!value) break;
        let range = this.quill.getSelection(true);
        if (range != null) {
          let index = range.index + range.length;
          this.quill.insertEmbed(index, this.root.getAttribute('data-mode'), value, Emitter.sources.USER);
          if (this.root.getAttribute('data-mode') === 'formula') {
            this.quill.insertText(index + 1, ' ', Emitter.sources.USER);
          }
          this.quill.setSelection(index + 2, Emitter.sources.USER);
        }
        break;
      }
      default:
    }
    this.textbox.value = '';
    this.hide();
  }
}

function extractVideoUrl(url) {
  let match = url.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtube\.com\/watch.*v=([a-zA-Z0-9_-]+)/) ||
              url.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtu\.be\/([a-zA-Z0-9_-]+)/);
  if (match) {
    return (match[1] || 'https') + '://www.youtube.com/embed/' + match[2] + '?showinfo=0';
  }
  if (match = url.match(/^(?:(https?):\/\/)?(?:www\.)?vimeo\.com\/(\d+)/)) {  // eslint-disable-line no-cond-assign
    return (match[1] || 'https') + '://player.vimeo.com/video/' + match[2] + '/';
  }
  return url;
}

function fillSelect(select, values, defaultValue = false) {
  values.forEach(function(value) {
    let option = document.createElement('option');
    if (value === defaultValue) {
      option.setAttribute('selected', 'selected');
    } else {
      option.setAttribute('value', value);
    }
    select.appendChild(option);
  });
}

export { BaseTooltip, BaseTheme as default };
<commit_msg>fix #1649<commit_after>import extend from 'extend';
import Delta from 'quill-delta';
import Emitter from '../core/emitter';
import Keyboard from '../modules/keyboard';
import Theme from '../core/theme';
import ColorPicker from '../ui/color-picker';
import IconPicker from '../ui/icon-picker';
import Picker from '../ui/picker';
import Tooltip from '../ui/tooltip';

const ALIGNS = [ false, 'center', 'right', 'justify' ];

const COLORS = [
  "#000000", "#e60000", "#ff9900", "#ffff00", "#008a00", "#0066cc", "#9933ff",
  "#ffffff", "#facccc", "#ffebcc", "#ffffcc", "#cce8cc", "#cce0f5", "#ebd6ff",
  "#bbbbbb", "#f06666", "#ffc266", "#ffff66", "#66b966", "#66a3e0", "#c285ff",
  "#888888", "#a10000", "#b26b00", "#b2b200", "#006100", "#0047b2", "#6b24b2",
  "#444444", "#5c0000", "#663d00", "#666600", "#003700", "#002966", "#3d1466"
];

const FONTS = [ false, 'serif', 'monospace' ];

const HEADERS = [ '1', '2', '3', false ];

const SIZES = [ 'small', false, 'large', 'huge' ];

class BaseTheme extends Theme {
  constructor(quill, options) {
    super(quill, options);
    let listener = (e) => {
      if (!document.body.contains(quill.root)) {
        return document.body.removeEventListener('click', listener);
      }
      if (this.tooltip != null && !this.tooltip.root.contains(e.target) &&
          document.activeElement !== this.tooltip.textbox && !this.quill.hasFocus()) {
        this.tooltip.hide();
      }
      if (this.pickers != null) {
        this.pickers.forEach(function(picker) {
          if (!picker.container.contains(e.target)) {
            picker.close();
          }
        });
      }
    };
    document.body.addEventListener('click', listener);
  }

  addModule(name) {
    let module = super.addModule(name);
    if (name === 'toolbar') {
      this.extendToolbar(module);
    }
    return module;
  }

  buildButtons(buttons, icons) {
    buttons.forEach((button) => {
      let className = button.getAttribute('class') || '';
      className.split(/\s+/).forEach((name) => {
        if (!name.startsWith('ql-')) return;
        name = name.slice('ql-'.length);
        if (icons[name] == null) return;
        if (name === 'direction') {
          button.innerHTML = icons[name][''] + icons[name]['rtl'];
        } else if (typeof icons[name] === 'string') {
          button.innerHTML = icons[name];
        } else {
          let value = button.value || '';
          if (value != null && icons[name][value]) {
            button.innerHTML = icons[name][value];
          }
        }
      });
    });
  }

  buildPickers(selects, icons) {
    this.pickers = selects.map((select) => {
      if (select.classList.contains('ql-align')) {
        if (select.querySelector('option') == null) {
          fillSelect(select, ALIGNS);
        }
        return new IconPicker(select, icons.align);
      } else if (select.classList.contains('ql-background') || select.classList.contains('ql-color')) {
        let format = select.classList.contains('ql-background') ? 'background' : 'color';
        if (select.querySelector('option') == null) {
          fillSelect(select, COLORS, format === 'background' ? '#ffffff' : '#000000');
        }
        return new ColorPicker(select, icons[format]);
      } else {
        if (select.querySelector('option') == null) {
          if (select.classList.contains('ql-font')) {
            fillSelect(select, FONTS);
          } else if (select.classList.contains('ql-header')) {
            fillSelect(select, HEADERS);
          } else if (select.classList.contains('ql-size')) {
            fillSelect(select, SIZES);
          }
        }
        return new Picker(select);
      }
    });
    let update = () => {
      this.pickers.forEach(function(picker) {
        picker.update();
      });
    };
    this.quill.on(Emitter.events.EDITOR_CHANGE, update);
  }
}
BaseTheme.DEFAULTS = extend(true, {}, Theme.DEFAULTS, {
  modules: {
    toolbar: {
      handlers: {
        formula: function() {
          this.quill.theme.tooltip.edit('formula');
        },
        image: function() {
          let fileInput = this.container.querySelector('input.ql-image[type=file]');
          if (fileInput == null) {
            fileInput = document.createElement('input');
            fileInput.setAttribute('type', 'file');
            fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon');
            fileInput.classList.add('ql-image');
            fileInput.addEventListener('change', () => {
              if (fileInput.files != null && fileInput.files[0] != null) {
                let reader = new FileReader();
                reader.onload = (e) => {
                  let range = this.quill.getSelection(true);
                  this.quill.updateContents(new Delta()
                    .retain(range.index)
                    .delete(range.length)
                    .insert({ image: e.target.result })
                  , Emitter.sources.USER);
                  this.quill.setSelection(range.index + 1, Emitter.sources.SILENT);
                  fileInput.value = "";
                }
                reader.readAsDataURL(fileInput.files[0]);
              }
            });
            this.container.appendChild(fileInput);
          }
          fileInput.click();
        },
        video: function() {
          this.quill.theme.tooltip.edit('video');
        }
      }
    }
  }
});

class BaseTooltip extends Tooltip {
  constructor(quill, boundsContainer) {
    super(quill, boundsContainer);
    this.textbox = this.root.querySelector('input[type="text"]');
    this.listen();
  }

  listen() {
    this.textbox.addEventListener('keydown', (event) => {
      if (Keyboard.match(event, 'enter')) {
        this.save();
        event.preventDefault();
      } else if (Keyboard.match(event, 'escape')) {
        this.cancel();
        event.preventDefault();
      }
    });
  }

  cancel() {
    this.hide();
  }

  edit(mode = 'link', preview = null) {
    this.root.classList.remove('ql-hidden');
    this.root.classList.add('ql-editing');
    if (preview != null) {
      this.textbox.value = preview;
    } else if (mode !== this.root.getAttribute('data-mode')) {
      this.textbox.value = '';
    }
    this.position(this.quill.getBounds(this.quill.selection.savedRange));
    this.textbox.select();
    this.textbox.setAttribute('placeholder', this.textbox.getAttribute(`data-${mode}`) || '');
    this.root.setAttribute('data-mode', mode);
  }

  restoreFocus() {
    let scrollTop = this.quill.scrollingContainer.scrollTop;
    this.quill.focus();
    this.quill.scrollingContainer.scrollTop = scrollTop;
  }

  save() {
    let value = this.textbox.value;
    switch(this.root.getAttribute('data-mode')) {
      case 'link': {
        let scrollTop = this.quill.root.scrollTop;
        if (this.linkRange) {
          this.quill.formatText(this.linkRange, 'link', value, Emitter.sources.USER);
          delete this.linkRange;
        } else {
          this.restoreFocus();
          this.quill.format('link', value, Emitter.sources.USER);
        }
        this.quill.root.scrollTop = scrollTop;
        break;
      }
      case 'video': {
        value = extractVideoUrl(value);
      } // eslint-disable-next-line no-fallthrough
      case 'formula': {
        if (!value) break;
        let range = this.quill.getSelection(true);
        if (range != null) {
          let index = range.index + range.length;
          this.quill.insertEmbed(index, this.root.getAttribute('data-mode'), value, Emitter.sources.USER);
          if (this.root.getAttribute('data-mode') === 'formula') {
            this.quill.insertText(index + 1, ' ', Emitter.sources.USER);
          }
          this.quill.setSelection(index + 2, Emitter.sources.USER);
        }
        break;
      }
      default:
    }
    this.textbox.value = '';
    this.hide();
  }
}

function extractVideoUrl(url) {
  let match = url.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtube\.com\/watch.*v=([a-zA-Z0-9_-]+)/) ||
              url.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtu\.be\/([a-zA-Z0-9_-]+)/);
  if (match) {
    return (match[1] || 'https') + '://www.youtube.com/embed/' + match[2] + '?showinfo=0';
  }
  if (match = url.match(/^(?:(https?):\/\/)?(?:www\.)?vimeo\.com\/(\d+)/)) {  // eslint-disable-line no-cond-assign
    return (match[1] || 'https') + '://player.vimeo.com/video/' + match[2] + '/';
  }
  return url;
}

function fillSelect(select, values, defaultValue = false) {
  values.forEach(function(value) {
    let option = document.createElement('option');
    if (value === defaultValue) {
      option.setAttribute('selected', 'selected');
    } else {
      option.setAttribute('value', value);
    }
    select.appendChild(option);
  });
}

export { BaseTooltip, BaseTheme as default };
<|endoftext|>