mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
feat(globe): render the tilt and north-up buttons from the globe actions store
The camera orientation controls publish whether the map is tilted and the camera's whole-degree heading instead of writing the buttons' attributes, and answer tilt and north-up through the globe actions store. The new GlobeCompass renders the heading, so a rotating camera re-renders only the compass. The store drops an unchanged camera state and keeps each clear owner's busy state, so the buttons show the shell that answers them: a shell replaced by a newer one, or disposed mid-clear, leaves the live shell's state alone, and an older shell that answers again shows its own. createOwners gains owns() and ownerOf().
This commit is contained in:
1 parent
7edf8a577e
commit
eccaeea0c4
15 files changed
+495
-180
No files matched your search
+122
-1
@@ -160,7 +160,7 @@ test('a host hook that answers without a promise, or throws, still gets a toast'
|
||||
}
|
||||
});
|
||||
|
||||
test('the shell answers the globe bar’s share and clear until it is disposed', async () => {
|
||||
test('the shell answers the globe bar until it is disposed', async () => {
|
||||
const calls = [];
|
||||
const owner = {
|
||||
_disposed: false,
|
||||
@@ -173,9 +173,130 @@ test('the shell answers the globe bar’s share and clear until it is disposed',
|
||||
store.act('share');
|
||||
store.act('clear');
|
||||
assert.deepEqual(calls, ['share', 'clear']);
|
||||
// A newer shell answers, and owns the busy state, until it goes.
|
||||
const newer = { _disposed: false, clearSelectedLayers: async () => {} };
|
||||
StyleManager.prototype._initClearSelectedLayersButton.call(newer);
|
||||
assert.equal(store.owns(owner._clearLayersToken, 'clear'), false);
|
||||
store.detach(newer._clearLayersToken);
|
||||
assert.equal(store.owns(owner._clearLayersToken, 'clear'), true);
|
||||
store.detach(owner._shareToken);
|
||||
store.detach(owner._clearLayersToken);
|
||||
store.act('share');
|
||||
store.act('clear');
|
||||
assert.deepEqual(calls, ['share', 'clear']);
|
||||
});
|
||||
|
||||
test('the shell’s camera controls answer tilt and north-up and publish their state', () => {
|
||||
const store = useGlobeActionsStore(applicationPinia());
|
||||
const navigations = [];
|
||||
const owner = {
|
||||
viewer: { camera: { heading: 0 } },
|
||||
_navigation: {
|
||||
runOrientation: (noun, navigate) => {
|
||||
navigations.push(noun);
|
||||
return navigate();
|
||||
},
|
||||
},
|
||||
_showToast() {},
|
||||
};
|
||||
StyleManager.prototype._initCameraOrientationControls.call(owner);
|
||||
assert.deepEqual(store.camera, { tilted: false, heading: 0 });
|
||||
store.act('tilt');
|
||||
store.act('northUp');
|
||||
assert.deepEqual(navigations, ['camera', 'camera']);
|
||||
|
||||
// Initialised again, the shell replaces its own owner.
|
||||
const first = owner._orientationToken;
|
||||
StyleManager.prototype._initCameraOrientationControls.call(owner);
|
||||
assert.notEqual(owner._orientationToken, first);
|
||||
assert.equal(store.owns(first, 'tilt'), false);
|
||||
assert.equal(store.owns(owner._orientationToken, 'tilt'), true);
|
||||
|
||||
// A newer shell owns what the buttons show.
|
||||
const newer = store.connect({ tilt() {} });
|
||||
owner.viewer.camera.heading = Math.PI / 2;
|
||||
owner._cameraOrientationControls.sync();
|
||||
assert.deepEqual(store.camera, { tilted: false, heading: 0 });
|
||||
store.detach(newer);
|
||||
owner.viewer.camera.heading = Math.PI;
|
||||
owner._cameraOrientationControls.sync();
|
||||
assert.deepEqual(store.camera, { tilted: false, heading: 180 });
|
||||
owner._cameraOrientationControls.destroy();
|
||||
store.detach(owner._orientationToken);
|
||||
});
|
||||
|
||||
test('a shell that goes after a newer one leaves the newer one’s bar state', () => {
|
||||
const store = useGlobeActionsStore(applicationPinia());
|
||||
const shellWith = () => {
|
||||
const owner = {
|
||||
_disposed: false,
|
||||
viewer: { camera: { heading: 0 } },
|
||||
_navigation: { runOrientation: (_noun, navigate) => navigate() },
|
||||
_showToast() {},
|
||||
clearSelectedLayers: async () => {},
|
||||
};
|
||||
StyleManager.prototype._initClearSelectedLayersButton.call(owner);
|
||||
StyleManager.prototype._initCameraOrientationControls.call(owner);
|
||||
return owner;
|
||||
};
|
||||
const older = shellWith();
|
||||
const newer = shellWith();
|
||||
newer.viewer.camera.heading = Math.PI / 2;
|
||||
newer._cameraOrientationControls.sync();
|
||||
StyleManager.prototype._publishClearBusy.call(newer, true);
|
||||
StyleManager.prototype._publishClearBusy.call(older, false);
|
||||
assert.equal(store.clearBusy, true);
|
||||
|
||||
older._cameraOrientationControls.destroy();
|
||||
StyleManager.prototype._releaseGlobeActions.call(older);
|
||||
assert.equal(store.clearBusy, true);
|
||||
assert.deepEqual(store.camera, { tilted: false, heading: 90 });
|
||||
|
||||
// The shell that answers resets its state as it goes.
|
||||
newer._cameraOrientationControls.destroy();
|
||||
StyleManager.prototype._releaseGlobeActions.call(newer);
|
||||
assert.equal(store.clearBusy, null);
|
||||
assert.equal(store.camera, null);
|
||||
// Its clear finishing after it went changes nothing.
|
||||
newer._disposed = true;
|
||||
StyleManager.prototype._publishClearBusy.call(newer, false);
|
||||
assert.equal(store.clearBusy, null);
|
||||
});
|
||||
|
||||
test('an older shell that answers again shows its clear and its unchanged camera', () => {
|
||||
const store = useGlobeActionsStore(applicationPinia());
|
||||
const shellWith = (heading) => {
|
||||
const owner = {
|
||||
_disposed: false,
|
||||
viewer: { camera: { heading } },
|
||||
_navigation: { runOrientation: (_noun, navigate) => navigate() },
|
||||
_showToast() {},
|
||||
clearSelectedLayers: async () => {},
|
||||
};
|
||||
StyleManager.prototype._initClearSelectedLayersButton.call(owner);
|
||||
StyleManager.prototype._initCameraOrientationControls.call(owner);
|
||||
return owner;
|
||||
};
|
||||
const older = shellWith(Math.PI / 2);
|
||||
StyleManager.prototype._publishClearBusy.call(older, true);
|
||||
const newer = shellWith(0);
|
||||
// The newer shell's bar does not show the older one's clear.
|
||||
assert.equal(store.clearBusy, null);
|
||||
older._cameraOrientationControls.sync();
|
||||
assert.deepEqual(store.camera, { tilted: false, heading: 0 });
|
||||
// Initialised again mid-clear, a shell keeps its clear on the button.
|
||||
StyleManager.prototype._publishClearBusy.call(newer, true);
|
||||
StyleManager.prototype._initClearSelectedLayersButton.call(newer);
|
||||
assert.equal(store.clearBusy, true);
|
||||
StyleManager.prototype._publishClearBusy.call(newer, false);
|
||||
newer._cameraOrientationControls.destroy();
|
||||
StyleManager.prototype._releaseGlobeActions.call(newer);
|
||||
assert.equal(store.camera, null);
|
||||
// The older shell's clear is the button's again, and the next frame it
|
||||
// draws puts its heading back.
|
||||
assert.equal(store.clearBusy, true);
|
||||
older._cameraOrientationControls.sync();
|
||||
assert.deepEqual(store.camera, { tilted: false, heading: 90 });
|
||||
older._cameraOrientationControls.destroy();
|
||||
StyleManager.prototype._releaseGlobeActions.call(older);
|
||||
});
|
||||
Reference in new issue
Block a user