2

I need to pick objects by clicking on them and a pop-up non modal dialog to display info about the object. It works as it should, however if the user clicks on any GUI item , including the dialog, and there is an object behind, the three js object will be picked, thus changing the info in the popup.

Here are the snippets.

document.addEventListener( 'mousedown', onDocumentMouseDown, false );

jQuery dialog generator:

function createDialog(title, text, top) {
      return $("<div class='dialog' title='" + title + "'><p id='bodyText'> " + text + "</p></div>")
      .dialog({ position: { my: ("right" + 0 + "top+" + top), at: "right top" },
      close : setDialogNull, });
}

onMouseDown function:

function onDocumentMouseDown( e ) {
    e.preventDefault();
    console.log(dialog);
    var mouseVector = new THREE.Vector3();
    mouseVector.x = 2 * (e.clientX / window.innerWidth ) - 1;
    mouseVector.y = 1 - 2 * ( e.clientY / window.innerHeight );
    var raycaster = new THREE.Raycaster();
    raycaster.setFromCamera( mouseVector, camera );
    var intersects = raycaster.intersectObjects(objectCollection );

    if (intersects.length > 0) {
        var selectedObject = intersects[0];
        console.log("Intersected object", intersects[0]);
        selectedObject.object.material = (selectedObject.object.material.wireframe) ? selectedBoxMaterial : unselectedBoxMaterial;

        var text = intersects[0].distance;
        var title = "Shelf info";

        if (dialog == false) {
            createDialog(title, text, offset);
            offset = offset - 50;
            console.log(offset);
            dialog = true;

            console.log(dialog);
        }   

        if (dialog == true) { 
            {jQuery("#bodyText").text(text);
        }
    }   
}

Other GUI elements are created with dat.GUI.

When searching about this issue most results are about Unity, and not being an experienced developer I don't really understand how to adapt to them.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ButterTofu
  • 25
  • 5

1 Answers1

1

Without more code to understand your setup and events it's difficult to know what the solution would be. I would give the element that holds your three.js a specific ID, and in onDocumentMouseDown, check if it's the active element. You may need to check for document.activeElement.parentElement.id, or whatever, depending on what your setup is.

function onDocumentMouseDown( e ) {
    if(document.activeElement.id != "myThreeJSElementID"){
        //some other element has been clicked so let's return with nothing:
        return;
    }
    e.preventDefault();
    console.log(dialog);
    var mouseVector = new THREE.Vector3();
    mouseVector.x = 2 * (e.clientX / window.innerWidth ) - 1;
    mouseVector.y = 1 - 2 * ( e.clientY / window.innerHeight );
    var raycaster = new THREE.Raycaster();
    raycaster.setFromCamera( mouseVector, camera );
    var intersects = raycaster.intersectObjects(objectCollection );

    if (intersects.length > 0) {
        var selectedObject = intersects[0];
        console.log("Intersected object", intersects[0]);
        selectedObject.object.material = (selectedObject.object.material.wireframe) ? selectedBoxMaterial : unselectedBoxMaterial;

        var text = intersects[0].distance;
        var title = "Shelf info";

        if (dialog == false) {
            createDialog(title, text, offset);
            offset = offset - 50;
            console.log(offset);
            dialog = true;

            console.log(dialog);
        }   

        if (dialog == true) { 
            {jQuery("#bodyText").text(text);
        }
    }   
}

More ideally you should be setting a specific event for your three.js container rather than using a global document event, but an exception should work for now. many code examples use document.addEventListener out of simplicity, not best practice.

Radio
  • 2,810
  • 1
  • 21
  • 43