mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 07:42:23 +00:00
Keep a settled flight in reach of a later failed lookup
A new voice fly-to now records the last flight that moved as the one it replaced, landed or not; only a still-flying one passes on its manual-input count. A slow lookup cancelled by a direct flight that landed, followed by a lookup that found nothing, used to drop the queued motion, and a cancelled direct flight in the same place let it fall back to an older landing.
This commit is contained in:
1 parent
b683b8a64b
commit
4c9b27dc20
2 files changed
+72
-9
No files matched your search
+13
-9
@@ -1144,11 +1144,14 @@ export function createGevActionRunner({
|
|||||||
runOptions,
|
runOptions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Chained fly-tos: a grab during the earlier one counts. The flight
|
// Chained fly-tos: a grab during an earlier one still flying counts.
|
||||||
// replaced is the last one that moved, past lookups that found nothing.
|
// The flight replaced is the last one that moved, past lookups that
|
||||||
|
// found nothing.
|
||||||
const prior = voiceFlightTarget(voiceFlight);
|
const prior = voiceFlightTarget(voiceFlight);
|
||||||
const replaced = prior && !prior.done ? prior : null;
|
const flight = trackVoiceFlight(
|
||||||
const flight = trackVoiceFlight(replaced?.inputCount, replaced);
|
prior && !prior.done ? prior.inputCount : undefined,
|
||||||
|
prior,
|
||||||
|
);
|
||||||
voiceFlight = flight;
|
voiceFlight = flight;
|
||||||
const flown = flyToRequestedLocation(viewer, args, {
|
const flown = flyToRequestedLocation(viewer, args, {
|
||||||
onFlightEnd: flight.settle,
|
onFlightEnd: flight.settle,
|
||||||
@@ -2961,10 +2964,10 @@ let voiceFlightCount = 0;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A voice flight's end: 'arrived', 'cancelled' or 'failed', settled once.
|
* A voice flight's end: 'arrived', 'cancelled' or 'failed', settled once.
|
||||||
* `replaced` is the last flight that moved, if still pending when this one
|
* `replaced` is the last flight that moved when this one began (past lookups
|
||||||
* began (past lookups that found nothing). It is kept only
|
* that found nothing), landed or not. It is kept only while this one may turn
|
||||||
* while this one may turn out to have moved nothing (a lookup that found no
|
* out to have moved nothing (a lookup that found no place), so a queued
|
||||||
* place), so a queued motion can look past it.
|
* motion can look past it to that flight and its outcome.
|
||||||
*/
|
*/
|
||||||
function trackVoiceFlight(
|
function trackVoiceFlight(
|
||||||
inputCount = manualCameraInputCount(),
|
inputCount = manualCameraInputCount(),
|
||||||
@@ -2996,7 +2999,8 @@ function trackVoiceFlight(
|
|||||||
* actually started. A lookup that found nothing moved nothing, so look past
|
* actually started. A lookup that found nothing moved nothing, so look past
|
||||||
* it to the flight it replaced, but never to one older than `start` (a flight
|
* it to the flight it replaced, but never to one older than `start` (a flight
|
||||||
* from an earlier reply). Null when every later lookup found nothing. With
|
* from an earlier reply). Null when every later lookup found nothing. With
|
||||||
* no `start`, the latest flight that started, however old.
|
* no `start`, the latest flight that started, back through lookups that
|
||||||
|
* found nothing.
|
||||||
*/
|
*/
|
||||||
function voiceFlightTarget(latest, start = null) {
|
function voiceFlightTarget(latest, start = null) {
|
||||||
let flight = latest;
|
let flight = latest;
|
||||||
|
|||||||
@@ -791,6 +791,65 @@ test('two lookups that found nothing in a row still leave the motion waiting for
|
|||||||
assert.equal((await moved).ok, true);
|
assert.equal((await moved).ok, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// A flight that already settled is still what a later failed lookup replaced.
|
||||||
|
test('a motion acts at a landed flight that a later failed lookup replaced', async (t) => {
|
||||||
|
t.after(() => interruptCameraMotion('test-cleanup'));
|
||||||
|
const { viewer, styleManager, flights } = tiltAfterFlightHarness();
|
||||||
|
const searches = [];
|
||||||
|
const runner = createGevActionRunner({
|
||||||
|
viewer,
|
||||||
|
styleManager,
|
||||||
|
dataManager: { layers: new Map(), getAll: () => [] },
|
||||||
|
searchNavigation: (_viewer, query, options) => new Promise((resolve) => {
|
||||||
|
searches.push({ query, options, resolve });
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const flyA = runner('fly_to_location', { query: 'Slow A' });
|
||||||
|
const moved = runner('move_camera', { motion: 'orbit' });
|
||||||
|
assert.equal((await runner('fly_to_location', { locationId: 'austin' })).ok, true);
|
||||||
|
flights[0].complete();
|
||||||
|
const flyC = runner('fly_to_location', { query: 'Nowhere C' });
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
// B's start made A's lookup stale; C then finds nothing.
|
||||||
|
searches[0].resolve({ cancelled: true });
|
||||||
|
searches[1].resolve(null);
|
||||||
|
assert.equal((await flyA).cancelled, true);
|
||||||
|
assert.equal((await flyC).ok, false);
|
||||||
|
const result = await moved;
|
||||||
|
assert.equal(result.ok, true, result.error);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('a motion refuses when the flight a later failed lookup replaced was cancelled', async () => {
|
||||||
|
const { viewer, styleManager, flights } = tiltAfterFlightHarness();
|
||||||
|
const searches = [];
|
||||||
|
const runner = createGevActionRunner({
|
||||||
|
viewer,
|
||||||
|
styleManager,
|
||||||
|
dataManager: { layers: new Map(), getAll: () => [] },
|
||||||
|
searchNavigation: (_viewer, query, options) => new Promise((resolve) => {
|
||||||
|
searches.push({ query, options, resolve });
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
assert.equal((await runner('fly_to_location', { locationId: 'austin' })).ok, true);
|
||||||
|
const moved = runner('move_camera', { motion: 'orbit' });
|
||||||
|
const flyA = runner('fly_to_location', { query: 'Slow A' });
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
// The motion sees Austin land, then follows A's lookup.
|
||||||
|
flights[0].complete();
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
assert.equal((await runner('fly_to_location', { locationId: 'austin' })).ok, true);
|
||||||
|
flights[1].cancel();
|
||||||
|
const flyC = runner('fly_to_location', { query: 'Nowhere C' });
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
searches[0].resolve({ cancelled: true });
|
||||||
|
searches[1].resolve(null);
|
||||||
|
assert.equal((await flyA).cancelled, true);
|
||||||
|
assert.equal((await flyC).ok, false);
|
||||||
|
const result = await moved;
|
||||||
|
assert.equal(result.ok, false);
|
||||||
|
assert.match(result.error, /did not arrive/);
|
||||||
|
});
|
||||||
|
|
||||||
test('a stale motion does not follow a newer reply\'s fly-to', async () => {
|
test('a stale motion does not follow a newer reply\'s fly-to', async () => {
|
||||||
const { viewer, styleManager, flights } = tiltAfterFlightHarness();
|
const { viewer, styleManager, flights } = tiltAfterFlightHarness();
|
||||||
const runner = createGevActionRunner({
|
const runner = createGevActionRunner({
|
||||||
|
|||||||
Reference in new issue
Block a user