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
Mouse camera controls can get temporarily 'stuck on' #2522
Comments
I think this bug is in At the very least, both classes should use the same button-tracking strategy. But ideally, we wouldn't have multiple independent button tracking systems in Cesium. |
Is it intentional that camera look is left out of the Navigation Instructions button on the top right? |
If you press/hold any mouse button first: Cesium has a recording problem: Button/key press/release recordings shouldn't depend on conditions, they should simply be recorded. |
@WarpDrive what's happening is that Cesium tracks buttons individually by both button and modifier, so it thinks that "LEFT" is a separate button from "SHIFT+LEFT", which is a separate button from "CTRL+LEFT". So, a mouse-down on LEFT, followed by a mouse-up on SHIFT-LEFT, releases a "different" button than the one that was down. You can do this the other way around too, push down on SHIFT-LEFT and release LEFT to get the other one stuck down, and then you can use the SHIFT key by itself (with no mouse button down) to look around. This is a bug, but it's fairly deep-rooted. The |
It would be nice if browsers would provide a list of pushed keys and buttons (like GamePad API does), in addition to providing changes to key/button states. If you hold a key/button down then the document loses focus (like clicking on the URL bar), then you let go of the key/button then go back to the document how the heck is the document going to know that the key/button was let go? When losing focus you could assume all keys are let go, but that might not be the case either. For example http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Camera%20Tutorial.html&label=Showcases press and hold w, then click on the URL bar, then let go of w, it doesn't fire a keyup event. |
This sadly remains a bug eight years later in v1.102. I was able to monkey patch the bug by monitoring for mousedown/mouseup pairs with mismatched modifier keys, and then forcibly calling the Cesium camera's mouseup handler function for the same modifier key that was used when the mouse went down (if any). This gets Cesium's internal state to correctly reflect the fact that the mouse button is no longer down, and the camera controls no longer get 'stuck'. const canvasEl = viewer.canvas;
const cameraEventAgg = viewer.scene.screenSpaceCameraController._aggregator;
let downModifiers = null;
function onpointerdown(e) {
if (e.pointerType == 'mouse') {
downModifiers = new CesiumModifiers(e.shiftKey, e.ctrlKey, e.altKey);
}
}
function onpointerup(e) {
if (e.pointerType == 'mouse') {
if (downModifiers && (
downModifiers.shift != e.shiftKey ||
downModifiers.ctrl != e.ctrlKey ||
downModifiers.alt != e.altKey)) {
const modifier = downModifiers?.toCesiumType();
downModifiers = null;
setTimeout(() => { // to ensure we don't cause further weird behavior, call the event handler in the next tick
const handler = cameraEventAgg._eventHandler;
if (handler) {
handler.getInputAction(domMouseButtonToCesiumEventType(e), modifier)();
downModifiers = null;
}
}, 0);
}
}
}
canvasEl.addEventListener('pointerdown', onpointerdown);
canvasEl.addEventListener('pointerup', onpointerup);
class CesiumModifiers {
constructor(shift, ctrl, alt) {
this.shift = shift;
this.ctrl = ctrl;
this.alt = alt;
}
toCesiumType() {
if (this.shift) return 0;
if (this.ctrl) return 1;
if (this.alt) return 2;
// none = undefined
}
}
function domMouseButtonToCesiumEventType(button) {
switch (button) {
case 0: return ScreenSpaceEventType.LEFT_UP;
case 1: return ScreenSpaceEventType.MIDDLE_UP;
case 2: return ScreenSpaceEventType.RIGHT_UP;
}
} |
@daguej Would you be able to open a PR with your fix so the monkey patch isn't necessary? 😀 |
This is best demonstrated by the following in Sandcastle:
To produce the issue, do the following in order:
Cesium now rotates the globe with mouse move even though both mouse buttons are up. Clicking the globe gets the camera controller back in the correct state.
Obviously this demo isn't actually doing anything with shift+drag, but my application is using it to start drawing regions.
controller.enableInputs
isfalse
during that interaction and changed back totrue
when it finishes, but this issue still occurs.Any suggestions for solutions at the application level are also welcome. I'm aware that I could re-implement all of the camera movement myself, but that seems a bit ridiculous.
The text was updated successfully, but these errors were encountered: