diff --git a/docs/examples/en/controls/DragControls.html b/docs/examples/en/controls/DragControls.html index 8671d98c049004..cb6ddd78119173 100644 --- a/docs/examples/en/controls/DragControls.html +++ b/docs/examples/en/controls/DragControls.html @@ -127,21 +127,6 @@

Methods

See the base [page:Controls] class for common methods.

-

[method:undefined connect] ()

-

- Adds the event listeners of the controls. -

- -

[method:undefined disconnect] ()

-

- Removes the event listeners of the controls. -

- -

[method:undefined dispose] ()

-

- Should be called if the controls is no longer required. -

-

Source

diff --git a/docs/examples/en/controls/TransformControls.html b/docs/examples/en/controls/TransformControls.html index 334ca36614f04c..8e91adadda2cc7 100644 --- a/docs/examples/en/controls/TransformControls.html +++ b/docs/examples/en/controls/TransformControls.html @@ -7,7 +7,7 @@ - [page:Object3D] → + [page:Controls] →

[name]

@@ -41,7 +41,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

[page:Camera camera]: The camera of the rendered scene.

- [page:HTMLDOMElement domElement]: The HTML element used for event listeners. + [page:HTMLDOMElement domElement]: The HTML element used for event listeners. (optional)

Creates a new instance of [name]. @@ -73,7 +73,7 @@

objectChange

Properties

-

See the base [page:Object3D] class for common properties.

+

See the base [page:Controls] class for common properties.

[property:String axis]

@@ -85,32 +85,16 @@

[property:Camera camera]

The camera of the rendered scene.

-

[property:HTMLDOMElement domElement]

-

- The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will - not set up new event listeners. -

-

[property:Boolean dragging]

Whether or not dragging is currently performed. Read-only property.

-

[property:Boolean enabled]

-

- Whether or not the controls are enabled. -

-

[property:String mode]

The current transformation mode. Possible values are "translate", "rotate" and "scale". Default is `translate`.

-

[property:Object3D object]

-

- The 3D object being controlled. -

-

[property:Number rotationSnap]

By default, 3D objects are continuously rotated. If you set this property to a numeric value (radians), you can define in which @@ -150,7 +134,7 @@

[property:Number translationSnap]

Methods

-

See the base [page:Object3D] class for common methods.

+

See the base [page:Controls] class for common methods.

[method:TransformControls attach] ( [param:Object3D object] )

@@ -167,9 +151,10 @@

[method:TransformControls detach] ()

Removes the current 3D object from the controls and makes the helper UI invisible.

-

[method:undefined dispose] ()

+

[method:Object3D getGizmo] ()

- Should be called if the controls is no longer required. + Returns the visual representation of the controls. Add the gizmo to your scene to visually transform the attached + 3D object.

[method:Raycaster getRaycaster] ()

diff --git a/editor/js/Viewport.js b/editor/js/Viewport.js index 3b04fc8b4f91c1..cbe2e3a42812f9 100644 --- a/editor/js/Viewport.js +++ b/editor/js/Viewport.js @@ -142,7 +142,7 @@ function Viewport( editor ) { } ); - sceneHelpers.add( transformControls ); + sceneHelpers.add( transformControls.getGizmo() ); // diff --git a/examples/jsm/controls/TransformControls.js b/examples/jsm/controls/TransformControls.js index 38ee44ae6f322a..fe24c66c1f36e3 100644 --- a/examples/jsm/controls/TransformControls.js +++ b/examples/jsm/controls/TransformControls.js @@ -1,6 +1,7 @@ import { BoxGeometry, BufferGeometry, + Controls, CylinderGeometry, DoubleSide, Euler, @@ -36,32 +37,22 @@ const _mouseDownEvent = { type: 'mouseDown', mode: null }; const _mouseUpEvent = { type: 'mouseUp', mode: null }; const _objectChangeEvent = { type: 'objectChange' }; -class TransformControls extends Object3D { +class TransformControls extends Controls { - constructor( camera, domElement ) { + constructor( camera, domElement = null ) { - super(); - - if ( domElement === undefined ) { - - console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' ); - domElement = document; + super( undefined, domElement ); - } + const root = new TransformControlsRoot( this ); + this._root = root; - this.isTransformControls = true; + const gizmo = new TransformControlsGizmo(); + this._gizmo = gizmo; + root.add( gizmo ); - this.visible = false; - this.domElement = domElement; - this.domElement.style.touchAction = 'none'; // disable touch scroll - - const _gizmo = new TransformControlsGizmo(); - this._gizmo = _gizmo; - this.add( _gizmo ); - - const _plane = new TransformControlsPlane(); - this._plane = _plane; - this.add( _plane ); + const plane = new TransformControlsPlane(); + this._plane = plane; + root.add( plane ); const scope = this; @@ -83,8 +74,8 @@ class TransformControls extends Object3D { if ( propValue !== value ) { propValue = value; - _plane[ propName ] = value; - _gizmo[ propName ] = value; + plane[ propName ] = value; + gizmo[ propName ] = value; scope.dispatchEvent( { type: propName + '-changed', value: value } ); scope.dispatchEvent( _changeEvent ); @@ -96,8 +87,8 @@ class TransformControls extends Object3D { } ); scope[ propName ] = defaultValue; - _plane[ propName ] = defaultValue; - _gizmo[ propName ] = defaultValue; + plane[ propName ] = defaultValue; + gizmo[ propName ] = defaultValue; } @@ -172,50 +163,38 @@ class TransformControls extends Object3D { this._onPointerMove = onPointerMove.bind( this ); this._onPointerUp = onPointerUp.bind( this ); - this.domElement.addEventListener( 'pointerdown', this._onPointerDown ); - this.domElement.addEventListener( 'pointermove', this._onPointerHover ); - this.domElement.addEventListener( 'pointerup', this._onPointerUp ); - - } - - // updateMatrixWorld updates key transformation variables - updateMatrixWorld( force ) { - - if ( this.object !== undefined ) { + if ( domElement !== null ) { - this.object.updateMatrixWorld(); - - if ( this.object.parent === null ) { - - console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' ); - - } else { + this.connect(); - this.object.parent.matrixWorld.decompose( this._parentPosition, this._parentQuaternion, this._parentScale ); + } - } + } - this.object.matrixWorld.decompose( this.worldPosition, this.worldQuaternion, this._worldScale ); + connect() { - this._parentQuaternionInv.copy( this._parentQuaternion ).invert(); - this._worldQuaternionInv.copy( this.worldQuaternion ).invert(); + this.domElement.addEventListener( 'pointerdown', this._onPointerDown ); + this.domElement.addEventListener( 'pointermove', this._onPointerHover ); + this.domElement.addEventListener( 'pointerup', this._onPointerUp ); - } + this.domElement.style.touchAction = 'none'; // disable touch scroll - this.camera.updateMatrixWorld(); - this.camera.matrixWorld.decompose( this.cameraPosition, this.cameraQuaternion, this._cameraScale ); + } - if ( this.camera.isOrthographicCamera ) { + disconnect() { - this.camera.getWorldDirection( this.eye ).negate(); + this.domElement.removeEventListener( 'pointerdown', this._onPointerDown ); + this.domElement.removeEventListener( 'pointermove', this._onPointerHover ); + this.domElement.removeEventListener( 'pointermove', this._onPointerMove ); + this.domElement.removeEventListener( 'pointerup', this._onPointerUp ); - } else { + this.domElement.style.touchAction = 'auto'; - this.eye.copy( this.cameraPosition ).sub( this.worldPosition ).normalize(); + } - } + getGizmo() { - super.updateMatrixWorld( force ); + return this._root; } @@ -555,10 +534,7 @@ class TransformControls extends Object3D { dispose() { - this.domElement.removeEventListener( 'pointerdown', this._onPointerDown ); - this.domElement.removeEventListener( 'pointermove', this._onPointerHover ); - this.domElement.removeEventListener( 'pointermove', this._onPointerMove ); - this.domElement.removeEventListener( 'pointerup', this._onPointerUp ); + this.disconnect(); this.traverse( function ( child ) { @@ -573,7 +549,7 @@ class TransformControls extends Object3D { attach( object ) { this.object = object; - this.visible = true; + this._root.visible = true; return this; @@ -583,9 +559,10 @@ class TransformControls extends Object3D { detach() { this.object = undefined; - this.visible = false; this.axis = null; + this._root.visible = false; + return this; } @@ -778,6 +755,64 @@ const _v1 = new Vector3(); const _v2 = new Vector3(); const _v3 = new Vector3(); +class TransformControlsRoot extends Object3D { + + constructor( controls ) { + + super(); + + this.isTransformControlsRoot = true; + + this.controls = controls; + this.visible = false; + + } + + // updateMatrixWorld updates key transformation variables + updateMatrixWorld( force ) { + + const controls = this.controls; + + if ( controls.object !== undefined ) { + + controls.object.updateMatrixWorld(); + + if ( controls.object.parent === null ) { + + console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' ); + + } else { + + controls.object.parent.matrixWorld.decompose( controls._parentPosition, controls._parentQuaternion, controls._parentScale ); + + } + + controls.object.matrixWorld.decompose( controls.worldPosition, controls.worldQuaternion, controls._worldScale ); + + controls._parentQuaternionInv.copy( controls._parentQuaternion ).invert(); + controls._worldQuaternionInv.copy( controls.worldQuaternion ).invert(); + + } + + controls.camera.updateMatrixWorld(); + controls.camera.matrixWorld.decompose( controls.cameraPosition, controls.cameraQuaternion, controls._cameraScale ); + + if ( controls.camera.isOrthographicCamera ) { + + controls.camera.getWorldDirection( controls.eye ).negate(); + + } else { + + controls.eye.copy( controls.cameraPosition ).sub( controls.worldPosition ).normalize(); + + } + + super.updateMatrixWorld( force ); + + } + +} + class TransformControlsGizmo extends Object3D { constructor() { diff --git a/examples/misc_controls_transform.html b/examples/misc_controls_transform.html index b19805c8ff63ec..12cf80d4c2b472 100644 --- a/examples/misc_controls_transform.html +++ b/examples/misc_controls_transform.html @@ -78,7 +78,6 @@ control = new TransformControls( currentCamera, renderer.domElement ); control.addEventListener( 'change', render ); - control.addEventListener( 'dragging-changed', function ( event ) { orbit.enabled = ! event.value; @@ -89,7 +88,9 @@ scene.add( mesh ); control.attach( mesh ); - scene.add( control ); + + const gizmo = control.getGizmo(); + scene.add( gizmo ); window.addEventListener( 'resize', onWindowResize ); diff --git a/examples/webgl_animation_skinning_ik.html b/examples/webgl_animation_skinning_ik.html index 90475be5bc4359..5537f3310df2cd 100644 --- a/examples/webgl_animation_skinning_ik.html +++ b/examples/webgl_animation_skinning_ik.html @@ -151,7 +151,7 @@ transformControls.showX = false; transformControls.space = 'world'; transformControls.attach( OOI.target_hand_l ); - scene.add( transformControls ); + scene.add( transformControls.getGizmo() ); // disable orbitControls while using transformControls transformControls.addEventListener( 'mouseDown', () => orbitControls.enabled = false ); diff --git a/examples/webgl_geometry_spline_editor.html b/examples/webgl_geometry_spline_editor.html index 9ec6fecd5064b0..c43358a5969b94 100644 --- a/examples/webgl_geometry_spline_editor.html +++ b/examples/webgl_geometry_spline_editor.html @@ -145,7 +145,7 @@ controls.enabled = ! event.value; } ); - scene.add( transformControl ); + scene.add( transformControl.getGizmo() ); transformControl.addEventListener( 'objectChange', function () { diff --git a/examples/webgl_modifier_curve.html b/examples/webgl_modifier_curve.html index 8e4dc45f880b63..22d3fe81654d1c 100644 --- a/examples/webgl_modifier_curve.html +++ b/examples/webgl_modifier_curve.html @@ -191,7 +191,7 @@ const target = intersects[ 0 ].object; control.attach( target ); - scene.add( control ); + scene.add( control.getGizmo() ); } diff --git a/examples/webgl_modifier_curve_instanced.html b/examples/webgl_modifier_curve_instanced.html index ac8e7fc035d7ef..5c65f7121d8153 100644 --- a/examples/webgl_modifier_curve_instanced.html +++ b/examples/webgl_modifier_curve_instanced.html @@ -221,7 +221,7 @@ const target = intersects[ 0 ].object; control.attach( target ); - scene.add( control ); + scene.add( control.getGizmo() ); } diff --git a/examples/webgl_shadowmap_progressive.html b/examples/webgl_shadowmap_progressive.html index 795046abbfe8b9..eb10c97247e324 100644 --- a/examples/webgl_shadowmap_progressive.html +++ b/examples/webgl_shadowmap_progressive.html @@ -76,7 +76,7 @@ } ); control.attach( lightOrigin ); - scene.add( control ); + scene.add( control.getGizmo() ); // create 8 directional lights to speed up the convergence for ( let l = 0; l < lightCount; l ++ ) { @@ -142,7 +142,7 @@ } ); control2.attach( object ); - scene.add( control2 ); + scene.add( control2.getGizmo() ); const lightTarget = new THREE.Group(); lightTarget.position.set( 0, 20, 0 ); for ( let l = 0; l < dirLights.length; l ++ ) { diff --git a/examples/webgpu_tsl_compute_attractors_particles.html b/examples/webgpu_tsl_compute_attractors_particles.html index b1e0128a06f769..86c78957904f65 100644 --- a/examples/webgpu_tsl_compute_attractors_particles.html +++ b/examples/webgpu_tsl_compute_attractors_particles.html @@ -118,7 +118,7 @@ attractor.controls.attach( attractor.reference ); attractor.controls.visible = true; attractor.controls.enabled = attractor.controls.visible; - scene.add( attractor.controls ); + scene.add( attractor.controls.getGizmo() ); attractor.controls.addEventListener( 'dragging-changed', ( event ) => { diff --git a/examples/webxr_xr_controls_transform.html b/examples/webxr_xr_controls_transform.html index 649a19835454d6..fe0d7572281fd9 100644 --- a/examples/webxr_xr_controls_transform.html +++ b/examples/webxr_xr_controls_transform.html @@ -162,7 +162,7 @@ controls = new TransformControls( camera, renderer.domElement ); controls.attach( group.children[ 0 ] ); - scene.add( controls ); + scene.add( controls.getGizmo() ); //