I’m using an ArcRotateCamera and my whole scene webpage is in an iframe. When I drag to rotate and leave the iframe with the cursor so the mouse up event fires while being outside, babylon thinks it is still rotating when re-entering the iframe. This is rather annoying, because when you click to drag again you don’t rotate, you zoom and pan enormously. This also happens when the mouse up event fires on any overlayed HTML element.
I basically need to detect the mouse up event anywhere in the browser and then tell babylon it’s time to stop rotating. Any ideas or other suggestions?
Interestingly enough this only happened when the path for the source attribute of the iframe was relative. When I tried an absolute version of the same webpage the camera wasn’t locked in rotation mode.
@Regit, by any chance, would you be able to provide any kind of example or code snippet so that I can attempt to repro? I’m gonna try to create an example in the meantime so that I can see if I can see what you’re seeing.
I extracted the issue from my project and uploaded it for you to look at here: https://regitgit.github.io/babylonjs-iframe/
Click on the image to open the iframe. Then drag to rotate and move anywhere out of the iframe. When you re-enter the rotating is locked.
This would also happen when you released on the ‘X’-exit button. But I’m currently toggling its pointer events on pointerdown/up. However this only gets checked inside the contentWindow of the iframe, maybe there is a way to check if the click event started on the contentWindow but ended outside of it?
Small update: I’m getting the pointer up event outside of the iframe simply by this: document.addEventListener('pointerup', function(event) { }
I read about a similar issue in this thread: https://forum.babylonjs.com/t/arccamera-iframe-mouseup-not-triggered/9251
But scene.simulatePointerUp() doesn’t work… Looks like scene.pick(1000, 500) doesn’t work as a parameter. The simulated event then still shows x: 0 y: 0. But even then it should still stop the rotation?
Here the event somewhat works. Looks like its fired at (0, 0), since the model rotates towards there. And you guessed it, the rotation is still locked, that’s probably why it rotates. But in the end the pointer up event doesn’t seem to cancel the rotation lock .
I want to shift the attention to this. I tested it in another project, same thing. No rotation lock in babylon scenes coming from an absolute path somewhere on the web.
This has to be a bug right?
Hey @Regit, thanks for the demo! It looks like the pointerup event isn’t being handled. I won’t be able to dig into it much more today but I’ll try to take a closer look at it either tomorrow or Monday.
You can actually scratch the idea of it having something to do with absolute/relative path. That was supposedly just the case in localhost, but makes no difference on actual web.
@PolygonalSun is in vacation for another 2 weeks, yup this is indeed this period of the year I bet he ll be looking into ASAP when he is back. If the fix is urgent, please let me know ?
For anyone interested: The workaround I’m using right now is PointerLock. Works pretty well and needs minimal setup. It also allows infinite rotation instead of the normal rotation that’s restricted by the canvas’ bounds. Maybe that’s a reason to keep it like this even if the issue is fixed.
You just have to initialize it and add it to pointerdown/pointerup. I do it right in the beginning after getting the canvas:
The only downside was that I couldn’t use dblclick on the canvas anymore because of the locking. But with minimal additional code you can “implement” your own dblclick.
Edit: Forgot to mention that now I do it like this there’s an exception being thrown:
Uncaught DOMException: Failed to execute 'setPointerCapture' on 'Element': InvalidStateError
at HTMLCanvasElement._pointerDownEvent (https://preview.babylonjs.com/babylon.js:16:3780802)
It isn’t interfering with anything it seems. Any idea how to catch it nontheless?
For our code, we add set a pointer capture so that the event data can be grabbed, event when the cursor leaves the element area. Because we set this as part of our standard input, it’s trying to setPointerCapture when there’s already a pointer lock active (a pointer capture can’t be set when a pointer lock is active, by design). That’s why you’re seeing that DOMException.
The odd thing is, the pointer capture SHOULD be capturing your event data, even when you leave the iframe and that’s what’s got me confused.