No longer able to cancel camera inputs with new _onCameraInputObservable

Previously, we were able to use scene.onPointerObservable in conjunction with eventState.skipNextObservers = true; to be able to do things like dragging meshes around our scene without causing the camera to pan. Now that it looks like the internal camera logic has been refactored to use a separate observable, we don’t have a good way of accomplishing this.

Does anyone have any suggestions? Essentially, what we’d like to do is override the camera controls in certain situations based on pointer inputs.

cc @PolygonalSun

It sounds like it might be a regression :frowning: @ghempton can you share a repro of what was working before in the playground ? @PolygonalSun will have a look ASAP

Here is a quick repro: Babylon.js Playground

On versions of babylon older than 5.32.2 the camera does not pan when you drag the mouse on top of the mesh.

Hey @ghempton, so what I’d recommend to do would be to try using scene.onPrePointerObservable to skip the next onPointerObservable call instead of just skipping the observers:

scene.onPrePointerObservable.add(eventData => {
        if (eventData.type === BABYLON.PointerEventTypes.POINTERMOVE && dragging) {
            eventData.skipOnPointerObservable = true;
        }
    });

scene.onPointerObservable.add(...

Here’s an example of it in your PG: https://playground.babylonjs.com/#5M0EAN#1

The reason for the change in behavior is that we have been working on trying to optimize input and picking. Because of this, we created an internal observable to handle camera input and gave it priority vs user defined observers.

In any case, if you’re looking to interrupt and prevent any observers from firing, I’d recommend using the onPrePointerObservable approach.

Hmm this is still going to present some issue because we will want to run custom logic. See this updated playground: https://playground.babylonjs.com/#5M0EAN#2

We will still want the console.log to run during mouse move. The tricky part here is that we also conditionalize the logic here on the result of the pick so moving all of our logic into the onPrePointerObservable won’t be sufficient.

I think this is a fairly common scenario.

While I’m not a big fan of working within the internal observable, you could try adding an observer to scene._onCameraInputObservable to skip:

// This will force the observable to skip camera movements
    scene._onCameraInputObservable.add((eventData, eventState) => {
        if(dragging) {
                eventState.skipNextObservers = true;
            }
    }, BABYLON.PointerEventTypes.POINTERMOVE, true);

You’ll just need to make sure that you have the mask as POINTERMOVE so that you know that you can throw those out. Here’s the PG with some updated code: Camera skipNextObservers issue | Babylon.js Playground (babylonjs.com)

Would this kind of scenario work?

I’m sure we could come up with some sort of hack to make this work, just feels a little disappointing to have to move in that direction. Would be ideal to have some sort of happy path to make something like this work.

1 Like

@PolygonalSun let s check tomorrow if there is something we can provide to help reach back a similar functionnality :slight_smile:

2 Likes

We talked more about this, and the plan is to revert the inputs to work under just onPointerObservable. Expect a PR to go live for this by early next week.

PR is live: Cameras: Modified cameras to work under onPointerObservable by PolygonalSun · Pull Request #13293 · BabylonJS/Babylon.js (github.com)

2 Likes

PR is merged

Hey @ghempton,
Would it be possible to get some more info on your use case? I know that you want to run some custom logic but is the general idea to be able to use onPointerObservable to run some code but prevent the camera from moving or is there something more specific that requires more precision/timing? I just want to make 100% sure that I understand the usage of skipNextObservers here.

Preventing the camera from moving is the main thing. The main use case is just dragging objects around the scene.

onPointerDown

  • check if relevant mesh is picked and store

onPointerMove

  • if mesh being dragged, skipNextObserver = true
  • do the dragging logic

I suppose it could make sense to simply detach controls from the camera in the onPointerDown logic, but it gets kind of nuanced (e.g. if we want to still allow a user to walk with keyboard while dragging an object e.g. in a FPS camera), but we could also control that by manipulating the camera directly.

When you say detach controls, do you mean using camera.detachControls() or just detaching the mouse control from the camera using camera.inputs.attached.mouse.detachControl()? The reason why I’m asking is that the second one can still be used to disable the mouse, while keeping keyboard controls and user-defined observers active (Example).

This could potentially work for us.