Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor: Add Multiple Mesh Selection with Ctrl key and right click #30360

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions editor/js/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ function Editor() {

geometryChanged: new Signal(),

readyForMultipleSelect: new Signal(),

objectSelected: new Signal(),
objectsMultipleSelected: new Signal(),
objectFocused: new Signal(),

objectAdded: new Signal(),
Expand Down Expand Up @@ -123,6 +126,7 @@ function Editor() {
this.mixer = new THREE.AnimationMixer( this.scene );

this.selected = null;
this.selectedObjects = [];
this.helpers = {};

this.cameras = {};
Expand Down
56 changes: 53 additions & 3 deletions editor/js/Selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ class Selector {
this.editor = editor;
this.signals = signals;

let readyForMultipleSelect = false;
// signals

signals.readyForMultipleSelect.add( ( isReady ) => {

readyForMultipleSelect = isReady;

} );

signals.intersectionsDetected.add( ( intersects ) => {

if ( intersects.length > 0 ) {
Expand All @@ -23,12 +30,28 @@ class Selector {
if ( object.userData.object !== undefined ) {

// helper
if ( readyForMultipleSelect ) {

this.selectMultiple( object.userData.object );

} else {

this.select( object.userData.object );

}

this.select( object.userData.object );

} else {

this.select( object );
if ( readyForMultipleSelect ) {

this.selectMultiple( object );

} else {

this.select( object );

}

}

Expand Down Expand Up @@ -72,6 +95,26 @@ class Selector {

}

selectMultiple( object ) {

if ( object === null ) {

this.editor.selectedObjects = [];
this.editor.config.setKey( 'selectedObjects', [] );
this.signals.objectsMultipleSelected.dispatch( [] );
this.editor.selected = null;
return;

}

const selectedObjects = [ ...this.editor.selectedObjects.filter( itm => itm !== object ), object ];
this.editor.selectedObjects = selectedObjects;
this.editor.config.setKey( 'selectedObjects', selectedObjects );
this.signals.objectsMultipleSelected.dispatch( selectedObjects );
this.editor.selected = object;

}

select( object ) {

if ( this.editor.selected === object ) return;
Expand All @@ -81,19 +124,26 @@ class Selector {
if ( object !== null ) {

uuid = object.uuid;
this.editor.selectedObjects = [ object ];

} else {

this.editor.selectedObjects = [];

}

this.editor.selected = object;
this.editor.config.setKey( 'selected', uuid );

this.editor.config.setKey( 'selected', uuid );
this.signals.objectSelected.dispatch( object );


}

deselect() {

this.select( null );
this.signals.objectsMultipleSelected.dispatch( null );

}

Expand Down
126 changes: 108 additions & 18 deletions editor/js/Viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,18 @@ function Viewport( editor ) {

//

const box = new THREE.Box3();
let selectedObjects = [];
let boxes = [ new THREE.Box3() ];

const selectionBox = new THREE.Box3Helper( box );
selectionBox.material.depthTest = false;
selectionBox.material.transparent = true;
selectionBox.visible = false;
sceneHelpers.add( selectionBox );
let selectionBoxes = [ new THREE.Box3Helper( boxes[ 0 ] ) ];
selectionBoxes[ 0 ].material.depthTest = false;
selectionBoxes[ 0 ].material.transparent = true;
selectionBoxes[ 0 ].visible = false;
sceneHelpers.add( selectionBoxes[ 0 ] );

let objectPositionOnDown = null;
let objectRotationOnDown = null;
let objectScaleOnDown = null;

const transformControls = new TransformControls( camera, container.dom );
transformControls.addEventListener( 'axis-changed', function () {

Expand Down Expand Up @@ -108,7 +108,16 @@ function Viewport( editor ) {

if ( ! objectPositionOnDown.equals( object.position ) ) {

editor.execute( new SetPositionCommand( editor, object, object.position, objectPositionOnDown ) );
selectedObjects.map( ( selectedObject ) => {

var direction = new THREE.Vector3();
direction.subVectors( object.position, objectPositionOnDown );

const newPosition = selectedObject === object ? object.position : new THREE.Vector3( direction.x + selectedObject.position.x, direction.y + selectedObject.position.y, direction.z + selectedObject.position.z );
editor.execute( new SetPositionCommand( editor, selectedObject, newPosition, objectPositionOnDown ) );

} );


}

Expand All @@ -118,7 +127,12 @@ function Viewport( editor ) {

if ( ! objectRotationOnDown.equals( object.rotation ) ) {

editor.execute( new SetRotationCommand( editor, object, object.rotation, objectRotationOnDown ) );
selectedObjects.map( ( selectedObject ) => {

editor.execute( new SetRotationCommand( editor, selectedObject, object.rotation, objectRotationOnDown ) );

} );


}

Expand All @@ -128,7 +142,12 @@ function Viewport( editor ) {

if ( ! objectScaleOnDown.equals( object.scale ) ) {

editor.execute( new SetScaleCommand( editor, object, object.scale, objectScaleOnDown ) );
selectedObjects.map( ( selectedObject ) => {

editor.execute( new SetScaleCommand( editor, selectedObject, object.scale, objectScaleOnDown ) );

} );


}

Expand Down Expand Up @@ -267,10 +286,34 @@ function Viewport( editor ) {

}

function onKeyDown( event ) {

if ( event.key === 'Control' ) {

signals.readyForMultipleSelect.dispatch( true );

}


}

function onKeyUp( event ) {

if ( event.key === 'Control' ) {

signals.readyForMultipleSelect.dispatch( false );

}

}

container.dom.addEventListener( 'mousedown', onMouseDown );
container.dom.addEventListener( 'touchstart', onTouchStart, { passive: false } );
container.dom.addEventListener( 'dblclick', onDoubleClick );

document.addEventListener( 'keydown', onKeyDown );
document.addEventListener( 'keyup', onKeyUp );

// controls need to be added *after* main logic,
// otherwise controls.enabled doesn't work.

Expand Down Expand Up @@ -404,16 +447,21 @@ function Viewport( editor ) {

signals.objectSelected.add( function ( object ) {

selectionBox.visible = false;
boxes = [ new THREE.Box3() ];
selectionBoxes.map( ( item ) => sceneHelpers.remove( item ) );
selectionBoxes = [ new THREE.Box3Helper( boxes[ 0 ] ) ];
selectedObjects = [ object ];
transformControls.detach();


if ( object !== null && object !== scene && object !== camera ) {

box.setFromObject( object, true );
boxes[ 0 ].setFromObject( object, true );

if ( box.isEmpty() === false ) {
if ( boxes[ 0 ].isEmpty() === false ) {

selectionBox.visible = true;
selectionBoxes[ 0 ].visible = true;
sceneHelpers.add( selectionBoxes[ 0 ] );

}

Expand All @@ -425,6 +473,47 @@ function Viewport( editor ) {

} );

signals.objectsMultipleSelected.add( function ( objectList ) {

boxes = [];
selectionBoxes.map( item => sceneHelpers.remove( item ) );
selectionBoxes = [];
selectedObjects = objectList;

objectList.map( ( object, index ) => {



if ( object !== null && object !== scene && object !== camera ) {

boxes.push( new THREE.Box3() );

selectionBoxes.push( new THREE.Box3Helper( boxes[ index ] ) );
selectionBoxes[ index ].material.depthTest = false;
selectionBoxes[ index ].material.transparent = true;
selectionBoxes[ index ].visible = false;

sceneHelpers.add( selectionBoxes[ index ] );

transformControls.detach();
boxes[ index ].setFromObject( object, true );

if ( boxes[ index ].isEmpty() === false ) {

selectionBoxes[ index ].visible = true;

}

transformControls.attach( object );

}


} );
render();

} );

signals.objectFocused.add( function ( object ) {

controls.focus( object );
Expand All @@ -435,7 +524,7 @@ function Viewport( editor ) {

if ( object !== undefined ) {

box.setFromObject( object, true );
boxes[ 0 ].setFromObject( object, true );

}

Expand All @@ -446,9 +535,10 @@ function Viewport( editor ) {

signals.objectChanged.add( function ( object ) {

if ( editor.selected === object ) {
const index = selectedObjects.findIndex( itm => itm == object );
if ( editor.selected === object || editor.selectedObjects.includes( object ) ) {

box.setFromObject( object, true );
boxes[ index !== - 1 ? index : 0 ].setFromObject( object, true );

}

Expand Down Expand Up @@ -781,7 +871,7 @@ function Viewport( editor ) {
if ( editor.selected !== null ) {

editor.selected.updateWorldMatrix( false, true ); // avoid frame late effect for certain skinned meshes (e.g. Michelle.glb)
selectionBox.box.setFromObject( editor.selected, true ); // selection box should reflect current animation state
selectionBoxes[ 0 ].box.setFromObject( editor.selected, true ); // selection box should reflect current animation state

}

Expand Down
Loading