mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
feat(data): the selection dispatcher treats an unowned pick as empty space
Task 10a moves flights onto the dispatcher; its old handler deselected on a pick nobody owns (an unclaimed entity), and only another layer's pick was not empty space. The dispatcher now does the same (after drill-through owners had their chance), and selectionDispatcherFor(engine) gives the application one dispatcher per engine. Tests for both.
This commit is contained in:
1 parent
9f1a0611fa
commit
8e702f0c3b
2 files changed
+56
-3
No files matched your search
@@ -9,8 +9,8 @@
|
||||
// onEmptyClick(ctx) a clean click (short, no drag) on the map or nothing;
|
||||
// onEscape() Escape.
|
||||
// The rules are the old handlers': a pick another layer owns is not empty
|
||||
// space; `passThrough` picks (trails) never take the click, the next pick
|
||||
// does; a `drillThrough` owner (local ADS-B) takes its object from under
|
||||
// space (a pick nobody owns is); `passThrough` picks (trails) never take the
|
||||
// click, the next pick does; a `drillThrough` owner (local ADS-B) takes its object from under
|
||||
// another layer's; a drag selects nothing; a pointer owned by a tool
|
||||
// (inputOwnership) selects nothing. Layers not moved yet keep their own
|
||||
// handlers: the dispatcher never acts on an id it does not own.
|
||||
@@ -125,6 +125,10 @@ export function createSelectionDispatcher(
|
||||
return;
|
||||
}
|
||||
}
|
||||
// A pick no layer owns (an unclaimed entity) is empty space, as it was
|
||||
// for the old handlers: only another layer's object is not.
|
||||
if (first.owner === null && isTrackingClickGesture(gesture))
|
||||
for (const owner of [...owners.values()]) owner.onEmptyClick?.(ctx);
|
||||
};
|
||||
|
||||
const onKey = (event) => {
|
||||
@@ -186,6 +190,23 @@ export function createSelectionDispatcher(
|
||||
};
|
||||
}
|
||||
|
||||
const dispatchers = new WeakMap();
|
||||
|
||||
/**
|
||||
* The application's one dispatcher for `engine`, created on first use (the
|
||||
* layers that moved onto the engine share it).
|
||||
* @param {import('../globe/contract.js').GlobeEngine} engine
|
||||
*/
|
||||
export function selectionDispatcherFor(engine) {
|
||||
if (!engine) return null;
|
||||
let dispatcher = dispatchers.get(engine);
|
||||
if (!dispatcher) {
|
||||
dispatcher = createSelectionDispatcher(engine);
|
||||
dispatchers.set(engine, dispatcher);
|
||||
}
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
function safely(run) {
|
||||
try {
|
||||
return run();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { createFakeEngine } from '../globe/testing/fakeEngine.js';
|
||||
import { createSelectionDispatcher } from './selectionDispatcher.js';
|
||||
import {
|
||||
createSelectionDispatcher,
|
||||
selectionDispatcherFor,
|
||||
} from './selectionDispatcher.js';
|
||||
import {
|
||||
isOwnedByOtherLayer,
|
||||
registerPickOwner,
|
||||
@@ -95,6 +98,22 @@ test("another layer's pick is not empty space, owned through the shared registry
|
||||
}
|
||||
});
|
||||
|
||||
test('a pick no layer owns is empty space, as for the old handlers', () => {
|
||||
const { dispatcher, click } = setup({ 10: [{ id: 'unclaimed-entity' }] });
|
||||
const flights = recorder();
|
||||
dispatcher.register('flights', {
|
||||
owns: (id) => id === 'x',
|
||||
...flights.handlers,
|
||||
});
|
||||
click(10);
|
||||
click(10, { ms: 900 });
|
||||
assert.deepEqual(
|
||||
flights.calls,
|
||||
[['empty', 0]],
|
||||
'a long press does not deselect',
|
||||
);
|
||||
});
|
||||
|
||||
test('trails do not take clicks: the object under a trail is selected', () => {
|
||||
const { dispatcher, click } = setup({
|
||||
10: [{ id: 'trail-ae01ce', owner: 'flights-trail' }, { id: 'ae01ce' }],
|
||||
@@ -173,3 +192,16 @@ test('unregister and destroy remove the subscriptions', () => {
|
||||
assert.equal(isOwnedByOtherLayer('other', 'a'), false);
|
||||
assert.ok(engine.fake.callsOf('input.on').length >= 1);
|
||||
});
|
||||
|
||||
test('the application has one dispatcher per engine', () => {
|
||||
const engine = createFakeEngine();
|
||||
const other = createFakeEngine();
|
||||
assert.equal(selectionDispatcherFor(engine), selectionDispatcherFor(engine));
|
||||
assert.notEqual(
|
||||
selectionDispatcherFor(engine),
|
||||
selectionDispatcherFor(other),
|
||||
);
|
||||
assert.equal(selectionDispatcherFor(null), null);
|
||||
selectionDispatcherFor(engine).destroy();
|
||||
selectionDispatcherFor(other).destroy();
|
||||
});
|
||||
Reference in new issue
Block a user