mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 07:42:23 +00:00
Hide a vessel's detection callout while its own card paints
With Vessels and Detection on, a vessel with an ambient card on the map also got its detection callout next to the bracket. The callout lane paints beneath the cards, so its text showed through the card's plate and covered the speed and course. The callout now gives way only to a card the shared overlay actually paints in the same frame. The overlay paints part of the published cards (shared budget, collisions, UI chrome), so a vessel whose card was dropped keeps its callout. The detection lane paints before the cards publish their paint rects, so getOverlayPaintRect has nothing for the current frame there. The new isOverlayEntryQueued answers from the paint queue that the overlay solves before painting. Vessel detection objects name their card in cardSourceId/cardEntryId.
This commit is contained in:
1 parent
7d8b80db0a
commit
652f3c8ea1
7 files changed
+194
-4
No files matched your search
@@ -1065,6 +1065,22 @@ export function getOverlayPaintRect(sourceId, entryId) {
|
||||
return rect && rect.key === key && rect.stamp === _frameStamp ? rect : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether an entry is queued to paint in the frame being painted. Custom lanes
|
||||
* run before the host's own entries, so `getOverlayPaintRect` has nothing for
|
||||
* this frame yet while they paint; this answers from the solved paint queue.
|
||||
* @param {string} sourceId
|
||||
* @param {string} entryId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isOverlayEntryQueued(sourceId, entryId) {
|
||||
if (_destroyed) return false;
|
||||
const record = _records.get(entryKey(String(sourceId), String(entryId)));
|
||||
return (
|
||||
!!record && record.queuedStamp === _frameStamp && record.queuedAlpha > 0.001
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the topmost interactive world-overlay entry at CSS-pixel coords.
|
||||
* @param {number} x
|
||||
@@ -1737,6 +1753,8 @@ function getProjectionRecord(entry) {
|
||||
contentAlpha: 1,
|
||||
altitudeAlpha: 1,
|
||||
sourceAlpha: 1,
|
||||
queuedStamp: 0,
|
||||
queuedAlpha: 0,
|
||||
protectedPlacement: null,
|
||||
distanceOptions: {},
|
||||
altitudeOptions: {},
|
||||
@@ -2254,6 +2272,14 @@ function addPaintItem(record, placement, temporalAlpha, selected) {
|
||||
item.zIndex = record.entry.zIndex;
|
||||
item.key = record.key;
|
||||
_paintQueue[_paintCount++] = item;
|
||||
// Read by `isOverlayEntryQueued` while the custom lanes paint, before this
|
||||
// item publishes its paint rect. Keyhole and sonar fades are left out.
|
||||
record.queuedStamp = _frameStamp;
|
||||
record.queuedAlpha =
|
||||
record.sourceAlpha *
|
||||
temporalAlpha *
|
||||
record.distanceAlpha *
|
||||
record.altitudeAlpha;
|
||||
}
|
||||
|
||||
function sourceCanPaint(sourceId) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
activateWorldOverlayAction,
|
||||
initWorldOverlay,
|
||||
subscribeWorldOverlayActions,
|
||||
isOverlayEntryQueued,
|
||||
isOverlayPointVisible,
|
||||
normalizeOverlayEntry,
|
||||
paintLaneForOverlayEntry,
|
||||
@@ -1213,6 +1214,43 @@ test('custom detection lane receives the shared host frame and paints below ordi
|
||||
env.cleanup();
|
||||
});
|
||||
|
||||
test('a detection lane sees which cards this frame will paint before they publish paint rects', () => {
|
||||
// The detection lane paints first, so a card's paint rectangle for this
|
||||
// frame does not exist yet when it runs. The queued check is what lets a
|
||||
// contact's callout give way to that contact's own card in the same frame.
|
||||
const env = installMockEnvironment({ width: 400, height: 300, dpr: 1 });
|
||||
initWorldOverlay(env.viewer);
|
||||
const seen = [];
|
||||
registerWorldOverlayPaintLane('detection', () => {
|
||||
seen.push({
|
||||
shown: isOverlayEntryQueued('cards', 'SHOWN'),
|
||||
hidden: isOverlayEntryQueued('hidden-cards', 'HIDDEN'),
|
||||
unknown: isOverlayEntryQueued('cards', 'NOT-PUBLISHED'),
|
||||
rect: getOverlayPaintRect('cards', 'SHOWN'),
|
||||
});
|
||||
}, { id: 'detection', active: true, target: 'detection' });
|
||||
setOverlayEntries('cards', [selectedEntry('SHOWN', {
|
||||
position: positionAtScreen(200, 150),
|
||||
})]);
|
||||
setOverlayEntries('hidden-cards', [selectedEntry('HIDDEN', {
|
||||
position: positionAtScreen(100, 100),
|
||||
})]);
|
||||
setOverlaySourceVisible('hidden-cards', false);
|
||||
|
||||
env.postRender.raise();
|
||||
assert.deepEqual(seen[0], { shown: true, hidden: false, unknown: false, rect: null },
|
||||
'the card is queued while its paint rect is still unpublished');
|
||||
assert.ok(getOverlayPaintRect('cards', 'SHOWN'), 'the card did paint after the lane');
|
||||
assert.equal(getOverlayPaintRect('hidden-cards', 'HIDDEN'), null);
|
||||
|
||||
clearOverlaySource('cards');
|
||||
env.postRender.raise();
|
||||
assert.equal(seen[1].shown, false, 'a card cleared since the last frame is no longer queued');
|
||||
destroyWorldOverlay();
|
||||
assert.equal(isOverlayEntryQueued('cards', 'SHOWN'), false);
|
||||
env.cleanup();
|
||||
});
|
||||
|
||||
test('custom-lane painter state is bracketed by host save/restore', () => {
|
||||
// A painter that leaks a clip or alpha must not corrupt later frames: the
|
||||
// host wraps every custom-lane painter in save/try/finally-restore. Pin the
|
||||
|
||||
Reference in new issue
Block a user