mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
feat(launches): render the replay vehicle overlay from a store
The launches layer keeps the replay state, projection and wording and presents the replay vehicle overlay through subscribeReplayOverlay(), sending nothing for an unchanged frame, so the portable launches entry stays free of Vue. The application shell publishes each presentation to the gev-mission-replay store and the scene chrome teleports the vehicle, orbit dot and callout into the globe container with the same markup, classes, mode, transform, rotation and sonar opacities. Hiding keeps the mode, place and text, as before.
This commit is contained in:
1 parent
e0bfa471ac
commit
9ea6d7e8aa
12 files changed
+253
-84
No files matched your search
@@ -54,6 +54,7 @@ import { applyLocaleChoice } from './localePicker.js';
|
||||
import { PanelNavigation } from './panelNavigation.js';
|
||||
import { applicationPinia, createUiRuntime } from './vueRuntime.js';
|
||||
import { useContextStore } from './stores/context.js';
|
||||
import { useMissionReplayStore } from './stores/missionReplay.js';
|
||||
import { useDisplayStore } from './stores/display.js';
|
||||
import { useLocaleStore } from './stores/locale.js';
|
||||
import { useLocationStore } from './stores/location.js';
|
||||
@@ -1036,6 +1037,14 @@ export class StyleManager extends ShellFacade {
|
||||
this._missionsPanelUnsubscribe = rocketLaunchesLayer?.subscribePanel?.(
|
||||
(view) => contextStore.publishMissions(view),
|
||||
);
|
||||
// And its replay vehicle overlay, which the scene chrome renders.
|
||||
const missionReplayStore = useMissionReplayStore(applicationPinia());
|
||||
this._missionReplayUnsubscribe?.();
|
||||
missionReplayStore.publish(null);
|
||||
this._missionReplayUnsubscribe =
|
||||
rocketLaunchesLayer?.subscribeReplayOverlay?.((view) =>
|
||||
missionReplayStore.publish(view),
|
||||
);
|
||||
}
|
||||
|
||||
/** Wire the independent Radio companion controls. */
|
||||
@@ -1786,6 +1795,9 @@ export class StyleManager extends ShellFacade {
|
||||
this._awarenessPanelUnsubscribe = null;
|
||||
this._missionsPanelUnsubscribe?.();
|
||||
this._missionsPanelUnsubscribe = null;
|
||||
this._missionReplayUnsubscribe?.();
|
||||
this._missionReplayUnsubscribe = null;
|
||||
useMissionReplayStore(applicationPinia()).publish(null);
|
||||
const contextStore = useContextStore(applicationPinia());
|
||||
contextStore.connectAwareness(null);
|
||||
contextStore.publishAwareness(null);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { markRaw, shallowRef } from 'vue';
|
||||
|
||||
/**
|
||||
* The Space Missions replay vehicle overlay as its view renders it. The
|
||||
* launches layer presents it through `subscribeReplayOverlay()` and the
|
||||
* application shell publishes each presentation here.
|
||||
*/
|
||||
export const useMissionReplayStore = defineStore('gev-mission-replay', () => {
|
||||
/**
|
||||
* `{visible, mode, thrusting, paused, transform, rotation, iconOpacity,
|
||||
* labelOpacity, title, detail}`, or null while the layer has no overlay.
|
||||
*/
|
||||
const overlay = shallowRef(null);
|
||||
|
||||
/** @param {?object} next A fresh presentation; every publish re-renders. */
|
||||
function publish(next) {
|
||||
overlay.value = next && markRaw(next);
|
||||
}
|
||||
|
||||
return { overlay, publish };
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { useLocationStore } from '../stores/location.js';
|
||||
import { useStatusStore } from '../stores/status.js';
|
||||
import { vClassToggle } from '../rail/classToggle.js';
|
||||
import ImagerySplitView from './panels/ImagerySplitView.vue';
|
||||
import MissionReplayOverlay from './panels/MissionReplayOverlay.vue';
|
||||
import DataPacks from './panels/DataPacks.vue';
|
||||
import SceneInteractions from './panels/SceneInteractions.vue';
|
||||
import SplitFlapText from './panels/SplitFlapText.vue';
|
||||
@@ -102,4 +103,5 @@ const vToastText = {
|
||||
<DataPacks />
|
||||
<SceneInteractions />
|
||||
<WindInspectionMarker />
|
||||
<MissionReplayOverlay />
|
||||
</template>
|
||||
@@ -0,0 +1,14 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useMissionReplayStore } from '../../stores/missionReplay.js';
|
||||
|
||||
// The replay vehicle, its orbit dot and callout over the globe, where the
|
||||
// launches layer places them after each rendered frame.
|
||||
const { overlay } = storeToRefs(useMissionReplayStore());
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport v-if="overlay" defer to="#cesiumContainer">
|
||||
<div class="mission-replay-vehicle-overlay" :class="{ 'is-thrusting': overlay.thrusting, 'is-paused': overlay.paused }" :hidden="!overlay.visible" aria-hidden="true" :data-mode="overlay.mode ?? undefined" :style="{ transform: overlay.transform ?? undefined, '--mission-replay-rotation': overlay.rotation ?? undefined }"><div class="mission-replay-flight-symbol" :style="{ opacity: overlay.iconOpacity ?? undefined }"><svg class="mission-replay-rocket" viewBox="0 0 48 72" aria-hidden="true"><path class="mission-replay-rocket-body" d="M24 5C16 14 14 27 15 45L9 54L18 51L24 58L30 51L39 54L33 45C34 27 32 14 24 5Z"></path><circle class="mission-replay-rocket-port" cx="24" cy="29" r="3.4"></circle></svg><svg class="mission-replay-thrust" viewBox="0 0 72 72" aria-hidden="true"><ellipse style="--thrust-index:0" cx="36" cy="7" rx="5" ry="1.8"></ellipse><ellipse style="--thrust-index:1" cx="36" cy="15" rx="8" ry="2.4"></ellipse><ellipse style="--thrust-index:2" cx="36" cy="24" rx="11" ry="3"></ellipse><ellipse style="--thrust-index:3" cx="36" cy="35" rx="15" ry="3.8"></ellipse><ellipse style="--thrust-index:4" cx="36" cy="48" rx="20" ry="4.7"></ellipse><ellipse style="--thrust-index:5" cx="36" cy="63" rx="26" ry="5.8"></ellipse></svg></div><div class="mission-replay-orbit-dot" aria-hidden="true" :style="{ opacity: overlay.iconOpacity ?? undefined }"></div><div class="mission-replay-overlay-callout" :style="{ opacity: overlay.labelOpacity ?? undefined }"><strong data-replay-overlay-title="">{{ overlay.title }}</strong><span data-replay-overlay-detail="">{{ overlay.detail }}</span></div></div>
|
||||
</Teleport>
|
||||
</template>
|
||||
Reference in new issue
Block a user