mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
79 lines
2.8 KiB
JavaScript
79 lines
2.8 KiB
JavaScript
export const CCTV_FOCUS_REQUEST_EVENT = 'gev:cctv-request-focus';
|
|
export const CCTV_WORLD_CLICK_FOCUS_DURATION_SEC = 1.9;
|
|
export const CCTV_ACTIVATION_RESULT = Object.freeze({
|
|
ACTIVATED: 'activated',
|
|
UNCHANGED: 'unchanged',
|
|
NOT_FOUND: 'not-found',
|
|
});
|
|
|
|
/**
|
|
* Activate a camera selected by an in-world user click, then request the UI's
|
|
* cockpit-safe explicit focus path. Programmatic activation and auto-hop do not
|
|
* call this function, so they cannot emit the request.
|
|
* @param {string} cameraId - Clicked camera ID.
|
|
* @param {(cameraId: string) => string} activate - Discriminated CCTV activation callback.
|
|
* @param {EventTarget} [eventTarget=window] - Dispatch target.
|
|
* @returns {boolean} Whether a real activation occurred and the request was sent.
|
|
*/
|
|
export function activateCctvCameraFromWorldClick(
|
|
cameraId,
|
|
activate,
|
|
eventTarget = window,
|
|
) {
|
|
if (!cameraId || typeof activate !== 'function') return false;
|
|
if (activate(cameraId) !== CCTV_ACTIVATION_RESULT.ACTIVATED) return false;
|
|
eventTarget.dispatchEvent(
|
|
new CustomEvent(CCTV_FOCUS_REQUEST_EVENT, {
|
|
detail: { cameraId },
|
|
}),
|
|
);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Register the UI focus-request listener and return an idempotent disposer that
|
|
* removes the exact callback reference supplied to addEventListener.
|
|
* @param {EventTarget|Object} eventTarget - Window-like event target.
|
|
* @param {(event: Event) => void} listener - Stable listener callback.
|
|
* @returns {() => void} Listener disposer.
|
|
*/
|
|
export function registerCctvFocusRequestListener(eventTarget, listener) {
|
|
if (
|
|
!eventTarget?.addEventListener ||
|
|
!eventTarget?.removeEventListener ||
|
|
typeof listener !== 'function'
|
|
)
|
|
return () => {};
|
|
eventTarget.addEventListener(CCTV_FOCUS_REQUEST_EVENT, listener);
|
|
let disposed = false;
|
|
return () => {
|
|
if (disposed) return;
|
|
disposed = true;
|
|
eventTarget.removeEventListener(CCTV_FOCUS_REQUEST_EVENT, listener);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Route one CCTV world-click request through StyleManager's existing explicit
|
|
* focus policy, preserving tracking release and cockpit refusal behavior.
|
|
* @param {CustomEvent|Object} event - Focus-request event.
|
|
* @param {(activate: Function, focus: Function) => *} runExplicitFocus - Policy path.
|
|
* @param {(cameraId: string, durationSec: number) => *} focusCamera - CCTV flight callback.
|
|
* @returns {*} Focus-path result, or false for a malformed request.
|
|
*/
|
|
export function routeCctvFocusRequest(event, runExplicitFocus, focusCamera) {
|
|
const cameraId = event?.detail?.cameraId;
|
|
if (
|
|
typeof cameraId !== 'string' ||
|
|
!cameraId ||
|
|
typeof runExplicitFocus !== 'function'
|
|
) {
|
|
return false;
|
|
}
|
|
return runExplicitFocus(
|
|
() => cameraId,
|
|
(selectedId) =>
|
|
focusCamera(selectedId, CCTV_WORLD_CLICK_FOCUS_DURATION_SEC),
|
|
);
|
|
}
|