mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-09 04:44:01 +00:00
fix(cockpit): keep the orbital view on a double-click at a ground point
In the orbital view a double-click on a mapped ground point went on to Cesium's own double-click, which tracks the picked entity and so ended the view. The Cockpit's double-click routing now takes it in orbit: it keeps or starts the focus on that point (a point beyond the reach is left unfocused but still not tracked). A double-click anywhere else, one a tool owns, and every one outside orbit go on to Cesium's as before, and stopping the Cockpit still hands Cesium's handler back.
This commit is contained in:
1 parent
dd063b0e83
commit
b18336d3d4
5 files changed
+116
-9
No files matched your search
@@ -1723,7 +1723,10 @@ in a polite live region (`FOCUS · Camp Alpha`), and the swath reads
|
||||
approximate as for a tilt, scaled by the tilt onto the point. Clicks still
|
||||
reach Cesium's own handler and never untrack the satellite; a click a tool
|
||||
owns (drawing) is ignored, and the draw tool still borrows the click while
|
||||
it draws. Under the readout, IN REACH · *n* (a disclosure) lists the mapped
|
||||
it draws. A double-click on a mapped ground point keeps or starts the focus
|
||||
on it and never reaches Cesium's double-click, which would track the point
|
||||
and end the view (the Cockpit's double-click routing in
|
||||
`src/ui/cockpitInput.js`); any other double-click goes on as before. Under the readout, IN REACH · *n* (a disclosure) lists the mapped
|
||||
points facing the satellite that are within the reach or in the frame now,
|
||||
nearest to nadir first, at most 12 (with NEAREST 12 OF *n* beyond that),
|
||||
rebuilt once a second. A row opens the point's details: position, source and
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
} from './cockpitOrbitalView.js';
|
||||
import {
|
||||
onOrbitalClick,
|
||||
onOrbitalDoubleClick,
|
||||
routeSceneClick,
|
||||
toggleOrbitalFocus,
|
||||
} from './cockpitOrbitalFocus.js';
|
||||
@@ -445,6 +446,15 @@ export class CockpitViewController {
|
||||
onOrbitalClick(position) {
|
||||
return onOrbitalClick.call(this, position);
|
||||
}
|
||||
/**
|
||||
* A double-click on the orbital picture: on a mapped ground point it keeps
|
||||
* or starts the focus there instead of letting Cesium track the point.
|
||||
* @param {{x: number, y: number}|null|undefined} position
|
||||
* @returns {boolean} True when it was taken.
|
||||
*/
|
||||
onOrbitalDoubleClick(position) {
|
||||
return onOrbitalDoubleClick.call(this, position);
|
||||
}
|
||||
/**
|
||||
* FOCUS on the reach list: focus that point, switch to it, or end the
|
||||
* focus held on it.
|
||||
|
||||
@@ -123,7 +123,8 @@ export function onSceneDoubleClick(position, nowMs = performance.now()) {
|
||||
* installs its own (pickAndTrackObject), which untracks whenever the pick is
|
||||
* not an Entity: on a followed aircraft's model, a primitive, it would drop
|
||||
* the very track the double-click means to ride. A double-click on the
|
||||
* followed track is the Cockpit's; any other goes on to Cesium's.
|
||||
* followed track is the Cockpit's, as is one on a mapped ground point in
|
||||
* orbit (a focus); any other goes on to Cesium's.
|
||||
* @returns {() => void} Puts Cesium's handler back, unless another owner
|
||||
* (the draw tool borrows it) has replaced ours since.
|
||||
*/
|
||||
@@ -134,6 +135,9 @@ export function routeSceneDoubleClick() {
|
||||
const stock = handler.getInputAction?.(type) ?? null;
|
||||
const routed = (event) => {
|
||||
if (this.onSceneDoubleClick(event?.position)) return;
|
||||
// In orbit, a double-click on a mapped ground point is a focus, never a
|
||||
// retarget that would end the view.
|
||||
if (this.onOrbitalDoubleClick?.(event?.position)) return;
|
||||
stock?.(event);
|
||||
};
|
||||
handler.setInputAction(routed, type);
|
||||
|
||||
@@ -168,6 +168,37 @@ export function toggleOrbitalFocus(key) {
|
||||
return record ? startFocus.call(this, record) : false;
|
||||
}
|
||||
|
||||
/** The mapped ground point drawn at a canvas position, or null. */
|
||||
function groundRecordAt(controller, position) {
|
||||
let picked = null;
|
||||
try {
|
||||
picked = controller.viewer.scene?.pick?.(position) ?? null;
|
||||
} catch {
|
||||
picked = null;
|
||||
}
|
||||
return pickedGroundRecord(controller, picked);
|
||||
}
|
||||
|
||||
/**
|
||||
* A double-click on the orbital picture. On a mapped ground point it keeps
|
||||
* or starts the focus on it (as a single click does) and is taken: Cesium's
|
||||
* own double-click would track that point, which ends the view. Any other
|
||||
* double-click, one a tool owns, and every one outside orbit go on.
|
||||
* @param {{x: number, y: number}|null|undefined} position Canvas position.
|
||||
* @returns {boolean} True when it landed on a ground point and was taken.
|
||||
*/
|
||||
export function onOrbitalDoubleClick(position) {
|
||||
if (!inOrbit(this) || !isPointerFree()) return false;
|
||||
if (!Number.isFinite(position?.x) || !Number.isFinite(position?.y))
|
||||
return false;
|
||||
const record = groundRecordAt(this, position);
|
||||
if (!record) return false;
|
||||
// A point beyond the reach is not focused, but still never tracked.
|
||||
if (this.orbital.focus?.key !== String(record.id))
|
||||
startFocus.call(this, record);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A click on the orbital picture. One on a mapped ground point in reach
|
||||
* focuses it; any other click ends a focus. A click a tool owns (drawing)
|
||||
@@ -179,13 +210,7 @@ export function onOrbitalClick(position) {
|
||||
if (!inOrbit(this) || !isPointerFree()) return false;
|
||||
if (!Number.isFinite(position?.x) || !Number.isFinite(position?.y))
|
||||
return false;
|
||||
let picked = null;
|
||||
try {
|
||||
picked = this.viewer.scene?.pick?.(position) ?? null;
|
||||
} catch {
|
||||
picked = null;
|
||||
}
|
||||
const record = pickedGroundRecord(this, picked);
|
||||
const record = groundRecordAt(this, position);
|
||||
const state = this.orbital;
|
||||
if (record) {
|
||||
if (state.focus?.key === String(record.id)) return true;
|
||||
|
||||
@@ -109,6 +109,18 @@ function fixture(t, { reducedMotion = false } = {}) {
|
||||
};
|
||||
handler.stock = stockClick;
|
||||
actions.set(Cesium.ScreenSpaceEventType.LEFT_CLICK, stockClick);
|
||||
// Its double-click tracks what it picks (pickAndTrackObject): a mapped
|
||||
// point, tracked, would end the orbital view.
|
||||
handler.stockDoubleClicks = 0;
|
||||
const stockDoubleClick = ({ position }) => {
|
||||
handler.stockDoubleClicks += 1;
|
||||
const picked = viewer.scene.pick(position);
|
||||
viewer.trackedEntity = picked?.id
|
||||
? { ...picked.id, position: { getValue: () => null } }
|
||||
: undefined;
|
||||
};
|
||||
handler.stockDouble = stockDoubleClick;
|
||||
actions.set(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK, stockDoubleClick);
|
||||
viewer.screenSpaceEventHandler = handler;
|
||||
|
||||
let subject = { ...ISS };
|
||||
@@ -229,6 +241,12 @@ function fixture(t, { reducedMotion = false } = {}) {
|
||||
frame,
|
||||
click: (position) =>
|
||||
actions.get(Cesium.ScreenSpaceEventType.LEFT_CLICK)?.({ position }),
|
||||
/** A double-click as Cesium fires it: two clicks, then the double. */
|
||||
doubleClick(position) {
|
||||
actions.get(Cesium.ScreenSpaceEventType.LEFT_CLICK)?.({ position });
|
||||
actions.get(Cesium.ScreenSpaceEventType.LEFT_CLICK)?.({ position });
|
||||
actions.get(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)?.({ position });
|
||||
},
|
||||
/** Move the satellite along its track by `deg` of latitude and longitude. */
|
||||
move(dLat, dLon) {
|
||||
subject = {
|
||||
@@ -642,3 +660,50 @@ test('stopping the Cockpit hands the single click back to Cesium', async (t) =>
|
||||
assert.equal(scene.handler.stockClicks, 1);
|
||||
assert.equal(scene.cockpit.orbital, null);
|
||||
});
|
||||
|
||||
test('a double-click on a mapped point focuses it and keeps the orbital view', async (t) => {
|
||||
const scene = await inOrbit(t);
|
||||
const { cockpit, viewer, handler } = scene;
|
||||
scene.doubleClick(SITES.alpha.at);
|
||||
assert.equal(handler.stockDoubleClicks, 0, 'Cesium does not track the point');
|
||||
assert.equal(viewer.trackedEntity, undefined);
|
||||
scene.frame();
|
||||
assert.equal(cockpit.active, true, 'still in orbit');
|
||||
assert.equal(cockpit.orbital.focus.key, 'site-alpha');
|
||||
run(scene, LAND_FRAMES);
|
||||
assert.ok(missDeg(scene.shots.at(-1), 'alpha') < 1e-5);
|
||||
|
||||
// On the focused point it keeps the focus; on another it switches.
|
||||
scene.doubleClick(SITES.alpha.at);
|
||||
assert.equal(cockpit.orbital.focus.key, 'site-alpha');
|
||||
scene.doubleClick(SITES.bravo.at);
|
||||
assert.equal(cockpit.orbital.focus.key, 'site-bravo');
|
||||
// A mapped point beyond the reach is not focused, but not tracked either.
|
||||
scene.doubleClick(SITES.far.at);
|
||||
assert.equal(handler.stockDoubleClicks, 0);
|
||||
scene.frame();
|
||||
assert.equal(cockpit.active, true);
|
||||
|
||||
// Anywhere else the double-click goes on to Cesium's, as before.
|
||||
scene.doubleClick(EMPTY_GROUND);
|
||||
assert.equal(handler.stockDoubleClicks, 1);
|
||||
assert.equal(cockpit.orbital.focus, null, 'the clicks ended the focus');
|
||||
});
|
||||
|
||||
test('a double-click a tool owns, or one outside orbit, goes on to Cesium', async (t) => {
|
||||
const scene = fixture(t);
|
||||
const type = Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK;
|
||||
scene.doubleClick(SITES.alpha.at);
|
||||
assert.equal(scene.handler.stockDoubleClicks, 1, 'outside orbit');
|
||||
scene.viewer.trackedEntity = undefined;
|
||||
assert.equal(scene.cockpit.enter(), true);
|
||||
await settle();
|
||||
scene.frame();
|
||||
const lease = claimPointer('draw');
|
||||
t.after(() => releasePointer(lease));
|
||||
scene.doubleClick(SITES.alpha.at);
|
||||
assert.equal(scene.handler.stockDoubleClicks, 2, 'a tool owns it');
|
||||
releasePointer(lease);
|
||||
scene.cockpit.stop();
|
||||
assert.equal(scene.handler.getInputAction(type), scene.handler.stockDouble);
|
||||
});
|
||||
Reference in new issue
Block a user