constructor( camera, domElement = null ) {

		super( undefined, domElement );

		const root = new TransformControlsRoot( this );
		this._root = root;

		const gizmo = new TransformControlsGizmo();
		this._gizmo = gizmo;
		root.add( gizmo );

		const plane = new TransformControlsPlane();
		this._plane = plane;
		root.add( plane );

		const scope = this;

		// Defined getter, setter and store for a property
		function defineProperty( propName, defaultValue ) {

			let propValue = defaultValue;

			Object.defineProperty( scope, propName, {

				get: function () {

					return propValue !== undefined ? propValue : defaultValue;

				},

				set: function ( value ) {

					if ( propValue !== value ) {

						propValue = value;
						plane[ propName ] = value;
						gizmo[ propName ] = value;

						scope.dispatchEvent( { type: propName + '-changed', value: value } );
						scope.dispatchEvent( _changeEvent );

					}

				}

			} );

			scope[ propName ] = defaultValue;
			plane[ propName ] = defaultValue;
			gizmo[ propName ] = defaultValue;

		}

		// Define properties with getters/setter
		// Setting the defined property will automatically trigger change event
		// Defined properties are passed down to gizmo and plane

		/**
		 * The camera of the rendered scene.
		 *
		 * @name TransformControls#camera
		 * @type {Camera}
		 */
		defineProperty( 'camera', camera );
		defineProperty( 'object', undefined );
		defineProperty( 'enabled', true );

		/**
		 * The current transformation axis.
		 *
		 * @name TransformControls#axis
		 * @type {string}
		 */
		defineProperty( 'axis', null );

		/**
		 * The current transformation axis.
		 *
		 * @name TransformControls#mode
		 * @type {('translate'|'rotate'|'scale')}
		 * @default 'translate'
		 */
		defineProperty( 'mode', 'translate' );

		/**
		 * By default, 3D objects are continuously translated. If you set this property to a numeric
		 * value (world units), you can define in which steps the 3D object should be translated.
		 *
		 * @name TransformControls#translationSnap
		 * @type {?number}
		 * @default null
		 */
		defineProperty( 'translationSnap', null );

		/**
		 * By default, 3D objects are continuously rotated. If you set this property to a numeric
		 * value (radians), you can define in which steps the 3D object should be rotated.
		 *
		 * @name TransformControls#rotationSnap
		 * @type {?number}
		 * @default null
		 */
		defineProperty( 'rotationSnap', null );

		/**
		 * By default, 3D objects are continuously scaled. If you set this property to a numeric
		 * value, you can define in which steps the 3D object should be scaled.
		 *
		 * @name TransformControls#scaleSnap
		 * @type {?number}
		 * @default null
		 */
		defineProperty( 'scaleSnap', null );

		/**
		 * Defines in which coordinate space transformations should be performed.
		 *
		 * @name TransformControls#space
		 * @type {('world'|'local')}
		 * @default 'world'
		 */
		defineProperty( 'space', 'world' );

		/**
		 * The size of the helper UI (axes/planes).
		 *
		 * @name TransformControls#size
		 * @type {number}
		 * @default 1
		 */
		defineProperty( 'size', 1 );

		/**
		 * Whether dragging is currently performed or not.
		 *
		 * @name TransformControls#dragging
		 * @type {boolean}
		 * @readonly
		 * @default false
		 */
		defineProperty( 'dragging', false );

		/**
		 * Whether the x-axis helper should be visible or not.
		 *
		 * @name TransformControls#showX
		 * @type {boolean}
		 * @default true
		 */
		defineProperty( 'showX', true );

		/**
		 * Whether the y-axis helper should be visible or not.
		 *
		 * @name TransformControls#showY
		 * @type {boolean}
		 * @default true
		 */
		defineProperty( 'showY', true );

		/**
		 * Whether the z-axis helper should be visible or not.
		 *
		 * @name TransformControls#showZ
		 * @type {boolean}
		 * @default true
		 */
		defineProperty( 'showZ', true );

		/**
		 * The minimum allowed X position during translation.
		 *
		 * @name TransformControls#minX
		 * @type {number}
		 * @default -Infinity
		 */
		defineProperty( 'minX', - Infinity );

		/**
		 * The maximum allowed X position during translation.
		 *
		 * @name TransformControls#maxX
		 * @type {number}
		 * @default Infinity
		 */
		defineProperty( 'maxX', Infinity );

		/**
		 * The minimum allowed y position during translation.
		 *
		 * @name TransformControls#minY
		 * @type {number}
		 * @default -Infinity
		 */
		defineProperty( 'minY', - Infinity );

		/**
		 * The maximum allowed Y position during translation.
		 *
		 * @name TransformControls#maxY
		 * @type {number}
		 * @default Infinity
		 */
		defineProperty( 'maxY', Infinity );

		/**
		 * The minimum allowed z position during translation.
		 *
		 * @name TransformControls#minZ
		 * @type {number}
		 * @default -Infinity
		 */
		defineProperty( 'minZ', - Infinity );

		/**
		 * The maximum allowed Z position during translation.
		 *
		 * @name TransformControls#maxZ
		 * @type {number}
		 * @default Infinity
		 */
		defineProperty( 'maxZ', Infinity );

		// Reusable utility variables

		const worldPosition = new Vector3();
		const worldPositionStart = new Vector3();
		const worldQuaternion = new Quaternion();
		const worldQuaternionStart = new Quaternion();
		const cameraPosition = new Vector3();
		const cameraQuaternion = new Quaternion();
		const pointStart = new Vector3();
		const pointEnd = new Vector3();
		const rotationAxis = new Vector3();
		const rotationAngle = 0;
		const eye = new Vector3();

		// TODO: remove properties unused in plane and gizmo

		defineProperty( 'worldPosition', worldPosition );
		defineProperty( 'worldPositionStart', worldPositionStart );
		defineProperty( 'worldQuaternion', worldQuaternion );
		defineProperty( 'worldQuaternionStart', worldQuaternionStart );
		defineProperty( 'cameraPosition', cameraPosition );
		defineProperty( 'cameraQuaternion', cameraQuaternion );
		defineProperty( 'pointStart', pointStart );
		defineProperty( 'pointEnd', pointEnd );
		defineProperty( 'rotationAxis', rotationAxis );
		defineProperty( 'rotationAngle', rotationAngle );
		defineProperty( 'eye', eye );

		this._offset = new Vector3();
		this._startNorm = new Vector3();
		this._endNorm = new Vector3();
		this._cameraScale = new Vector3();

		this._parentPosition = new Vector3();
		this._parentQuaternion = new Quaternion();
		this._parentQuaternionInv = new Quaternion();
		this._parentScale = new Vector3();

		this._worldScaleStart = new Vector3();
		this._worldQuaternionInv = new Quaternion();
		this._worldScale = new Vector3();

		this._positionStart = new Vector3();
		this._quaternionStart = new Quaternion();
		this._scaleStart = new Vector3();

		this._getPointer = getPointer.bind( this );
		this._onPointerDown = onPointerDown.bind( this );
		this._onPointerHover = onPointerHover.bind( this );
		this._onPointerMove = onPointerMove.bind( this );
		this._onPointerUp = onPointerUp.bind( this );

		if ( domElement !== null ) {

			this.connect( domElement );

		}

	}
Constructs a new controls instance.

@param {Camera} camera - The camera of the rendered scene.
@param {?HTMLDOMElement} domElement - The HTML element used for event listeners.