mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-14 15:22:21 +00:00
feat(cockpit): enter Cockpit with only the ridden aircraft's layer on
Cockpit entry no longer needs Contacts or both flight feeds: a civilian aircraft needs Live Flights, a military one Military Flights. Contacts and every other layer can be turned on or off before or during a session, and turning off the ridden layer ends it. A Context mode change in flight still blocks entry. When the other air feed is off, Live Signals and the Contact card say FLIGHTS FEED OFF or MILITARY FEED OFF · PARTIAL PICTURE instead of presenting a partial picture as complete. Voice refuses entry with subject-layer-off rather than contacts-inactive, and its tool description says Contacts is not required. Double-clicking the followed aircraft enters Cockpit through the same gate. The Cockpit takes the scene's double-click before Cesium's stock handler, which would otherwise untrack a followed aircraft whose model is a primitive. The entry also shows under the Intel HUD readout, sharing the Contacts button's face. A test keeps the classes the Cockpit adds to the body from matching another element's rule.
This commit is contained in:
1 parent
82f17e694e
commit
219f3e1079
37 files changed
+964
-134
No files matched your search
@@ -1,5 +1,99 @@
|
||||
/** Route Cockpit keys while preserving the active disclosure and form-control owner. */
|
||||
import * as Cesium from 'cesium';
|
||||
import { isPointerFree } from '../data/inputOwnership.js';
|
||||
|
||||
/** How far from the followed track a double-click may land, CSS pixels. */
|
||||
export const SUBJECT_DOUBLE_CLICK_RADIUS_PX = 32;
|
||||
|
||||
/**
|
||||
* Whether a double-click landed on the followed track's mark.
|
||||
* @param {{x: number, y: number}|null} click Canvas position of the click.
|
||||
* @param {{x: number, y: number}|null|undefined} subject Canvas position of
|
||||
* the track, or nothing when it is off screen.
|
||||
* @param {number} [radiusPx]
|
||||
*/
|
||||
export function doubleClickHitsSubject(
|
||||
click,
|
||||
subject,
|
||||
radiusPx = SUBJECT_DOUBLE_CLICK_RADIUS_PX,
|
||||
) {
|
||||
if (!click || !subject) return false;
|
||||
const distance = Math.hypot(click.x - subject.x, click.y - subject.y);
|
||||
return Number.isFinite(distance) && distance <= radiusPx;
|
||||
}
|
||||
|
||||
/** Where the track `kind` would ride is drawn now, as a world position. */
|
||||
function subjectWorldPosition(kind) {
|
||||
if (kind !== 'aircraft') return null;
|
||||
return (
|
||||
this.viewer.trackedEntity?.position?.getValue?.(
|
||||
this.viewer.clock?.currentTime,
|
||||
) ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/** The followed track's canvas position now, or null off screen. */
|
||||
function subjectCanvasPosition() {
|
||||
const kind = this.resolveEntryKind();
|
||||
const world = kind ? subjectWorldPosition.call(this, kind) : null;
|
||||
const scene = this.viewer.scene;
|
||||
if (!world || typeof scene?.cartesianToCanvasCoordinates !== 'function')
|
||||
return null;
|
||||
return (
|
||||
scene.cartesianToCanvasCoordinates(world, new Cesium.Cartesian2()) ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter first person when the followed track itself is double-clicked: the
|
||||
* same entry, and the same gates, as C and the entry buttons. A
|
||||
* double-click anywhere else, or one a tool owns (drawing ends a shape with
|
||||
* one), is left alone.
|
||||
* @param {{x: number, y: number}|null|undefined} position Canvas position.
|
||||
* @returns {boolean} True when it landed on the followed track, entered or
|
||||
* refused by the gate: the caller does nothing else with it.
|
||||
*/
|
||||
export function onSceneDoubleClick(position) {
|
||||
if (this.active || this.destroyed || !isPointerFree()) return false;
|
||||
if (!Number.isFinite(position?.x) || !Number.isFinite(position?.y))
|
||||
return false;
|
||||
if (!doubleClickHitsSubject(position, subjectCanvasPosition.call(this)))
|
||||
return false;
|
||||
this.enter();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the scene's double-click through the Cockpit first. Cesium's Viewer
|
||||
* 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.
|
||||
* @returns {() => void} Puts Cesium's handler back, unless another owner
|
||||
* (the draw tool borrows it) has replaced ours since.
|
||||
*/
|
||||
export function routeSceneDoubleClick() {
|
||||
const handler = this.viewer.screenSpaceEventHandler;
|
||||
if (typeof handler?.setInputAction !== 'function') return () => {};
|
||||
const type = Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK;
|
||||
const stock = handler.getInputAction?.(type) ?? null;
|
||||
const routed = (event) => {
|
||||
if (this.onSceneDoubleClick(event?.position)) return;
|
||||
stock?.(event);
|
||||
};
|
||||
handler.setInputAction(routed, type);
|
||||
return () => {
|
||||
if (handler.isDestroyed?.() || handler.getInputAction?.(type) !== routed)
|
||||
return;
|
||||
if (stock) handler.setInputAction(stock, type);
|
||||
else handler.removeInputAction(type);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The Cockpit's capture-phase keydown: Escape and C.
|
||||
* @param {KeyboardEvent} event
|
||||
*/
|
||||
export function onKeyDown(event) {
|
||||
if (this.destroyed) return false;
|
||||
if (event.repeat || event.isComposing) return;
|
||||
|
||||
Reference in new issue
Block a user