From aed08107bc8a3948cc2180dbe4f87c62a823a37c Mon Sep 17 00:00:00 2001 From: Aurora Luna Takemi <98479040+auroraisluna@users.noreply.github.com> Date: Fri, 24 Nov 2023 09:33:17 +0200 Subject: [PATCH 1/2] fix(hoppie): Updated Hoppie Poll rate (#8283) * Update HoppieConnector.ts * Update timings * fix lint * Update fbw-common/src/systems/datalink/router/src/webinterfaces/HoppieConnector.ts Co-authored-by: Michael Corcoran * Update fbw-common/src/systems/datalink/router/src/webinterfaces/HoppieConnector.ts Co-authored-by: Michael Corcoran --------- Co-authored-by: Michael Corcoran --- .../datalink/router/src/webinterfaces/HoppieConnector.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fbw-common/src/systems/datalink/router/src/webinterfaces/HoppieConnector.ts b/fbw-common/src/systems/datalink/router/src/webinterfaces/HoppieConnector.ts index 50f9f7d3c95..03f200d990e 100644 --- a/fbw-common/src/systems/datalink/router/src/webinterfaces/HoppieConnector.ts +++ b/fbw-common/src/systems/datalink/router/src/webinterfaces/HoppieConnector.ts @@ -375,7 +375,13 @@ export class HoppieConnector { } } + /** + * Gets the interval to poll the Hoppie API in milliseconds. + * Warning: This will return a different random time on each invocation! + * @returns The polling interval in milliseconds. + */ public static pollInterval(): number { - return 5000; + // To comply with Hoppie rate limits, we choose a random number between 45 and 75, as recommend by Hoppie. Ref to: https://www.hoppie.nl/acars/system/tech.html + return Math.random() * 30_000 + 45_000; } } From 4825cd3d7d2ef00e0fe19eadf4d29aa38fd20e89 Mon Sep 17 00:00:00 2001 From: Benjamin Dupont <4503241+Benjozork@users.noreply.github.com> Date: Sat, 25 Nov 2023 09:05:08 -0500 Subject: [PATCH 2/2] refactor(nd): move ND to fbw-common and create A380 ND (#8312) * refactor: remove old React ND sources * refactor: move additional things, including EFIS types, into fbw-common * refactor: move additional things into fbw-common * refactor: move ND to fbw-common * fix: add missing A380X_Simvars.js file * refactor: copy MsfsAvionicsCommon files to fbw-a380x/ * refactor: port CdsDisplayUnit to msfs-avionics * feat: add A380 ND * fix: re-add DisplayUnit to A320 * fix: ND build * fix: lint * fix: lint * fix: lint * fix: CdsDisplayUnit styling * fix: react CdsDisplayUnit -> LegacyCdsDisplayUnit --- .gitignore | 1 + .../components/fms-messages/FmsMessages.ts | 3 +- .../src/components/fms-messages/GpsPrimary.ts | 7 +- .../components/fms-messages/GpsPrimaryLost.ts | 4 +- .../fms-messages/MapPartlyDisplayed.ts | 4 +- .../components/fms-messages/RwyLsMismatch.ts | 4 +- .../fms-messages/SpecifiedNdbUnavailable.ts | 3 +- .../fms-messages/SpecifiedVorUnavailable.ts | 4 +- .../src/components/fms-messages/StepAhead.ts | 7 +- .../components/fms-messages/StepDeleted.ts | 7 +- .../src/components/fms-messages/TdReached.ts | 7 +- .../src/components/fms-messages/TuneNavaid.ts | 3 +- .../fms-messages/TurnAreaExceedance.ts | 4 +- .../src/systems/fmgc/src/efis/EfisCommon.ts | 2 +- .../src/systems/fmgc/src/efis/EfisSymbols.ts | 8 +- .../src/systems/fmgc/src/efis/EfisVectors.ts | 4 +- .../src/systems/fmgc/src/guidance/FmsState.ts | 2 +- .../fmgc/src/guidance/GuidanceController.ts | 6 +- .../fmgc/src/guidance/lnav/PseudoWaypoints.ts | 2 +- .../MsfsAvionicsCommon/AdirsValueProvider.tsx | 8 +- .../providers/DmcPublisher.tsx | 3 +- .../providers/EgpwcBusPublisher.ts | 6 +- .../providers/FcuBusPublisher.ts | 6 +- .../instruments/src/ND/FmsSymbolsPublisher.ts | 4 +- .../instruments/src/ND/NDControlEvents.ts | 6 +- .../systems/instruments/src/ND/instrument.tsx | 37 +- .../systems/instruments/src/ND/tsconfig.json | 3 +- .../instruments/src/ND_legacy/DebugInfo.tsx | 56 -- .../src/ND_legacy/elements/Chrono.tsx | 62 -- .../src/ND_legacy/elements/CrossTrack.tsx | 48 - .../src/ND_legacy/elements/FlightPlan.tsx | 571 ----------- .../ND_legacy/elements/FlightPlanVectors.tsx | 141 --- .../src/ND_legacy/elements/LnavStatus.tsx | 22 - .../src/ND_legacy/elements/RadioNavInfo.tsx | 166 ---- .../src/ND_legacy/elements/RadioNeedles.tsx | 117 --- .../src/ND_legacy/elements/SpeedIndicator.tsx | 34 - .../elements/TerrainMapThresholds.tsx | 82 -- .../elements/ToWaypointIndicator.tsx | 90 -- .../src/ND_legacy/elements/TopMessages.tsx | 80 -- .../src/ND_legacy/elements/TrackLine.tsx | 46 - .../src/ND_legacy/elements/Traffic.tsx | 336 ------- .../src/ND_legacy/elements/WindIndicator.tsx | 61 -- .../elements/messages/FMMessages.tsx | 60 -- .../messages/NavigationDisplayMessages.tsx | 70 -- .../elements/messages/TcasWxrMessages.tsx | 79 -- .../instruments/src/ND_legacy/index.tsx | 183 ---- .../src/ND_legacy/pages/ArcMode.tsx | 694 ------------- .../src/ND_legacy/pages/PlanMode.tsx | 116 --- .../src/ND_legacy/pages/RoseMode.tsx | 929 ------------------ .../instruments/src/PFD/AltitudeIndicator.tsx | 5 +- .../src/PFD/AttitudeIndicatorFixed.tsx | 4 +- .../src/PFD/AttitudeIndicatorHorizon.tsx | 5 +- .../src/PFD/DigitalAltitudeReadout.tsx | 4 +- .../src/systems/instruments/src/PFD/FMA.tsx | 6 +- .../src/PFD/FlightPathDirector.tsx | 4 +- .../instruments/src/PFD/FlightPathVector.tsx | 4 +- .../instruments/src/PFD/HeadingIndicator.tsx | 7 +- .../instruments/src/PFD/HorizontalTape.tsx | 7 +- .../src/PFD/LandingSystemIndicator.tsx | 4 +- .../src/systems/instruments/src/PFD/PFD.tsx | 6 +- .../instruments/src/PFD/SpeedIndicator.tsx | 4 +- .../src/PFD/VerticalSpeedIndicator.tsx | 4 +- .../instruments/src/PFD/instrument.tsx | 7 +- .../src/PFD/shared/ArincValueProvider.ts | 4 +- .../src/PFD/shared/PFDSimvarPublisher.tsx | 7 +- .../src/PFD/shared/SimplaneValueProvider.ts | 7 +- fbw-a380x/.env | 5 + fbw-a380x/mach.config.js | 1 + .../html_ui/JS/fbw-a380x/A380X_Simvars.js | 93 ++ .../src/systems/instruments/src/.eslintrc | 10 + ...splayUnit.tsx => LegacyCdsDisplayUnit.tsx} | 2 +- .../src/EWD/EngineWarningDisplay.tsx | 6 +- .../src/MFD/MultiFunctionDisplay.tsx | 6 +- .../src/systems/instruments/src/MFD/index.tsx | 2 +- .../src/MsfsAvionicsCommon/.eslintrc.js | 10 + .../MsfsAvionicsCommon/AdirsValueProvider.tsx | 59 ++ .../src/MsfsAvionicsCommon/CdsDisplayUnit.tsx | 278 ++++++ .../src/MsfsAvionicsCommon/Layer.tsx | 29 + .../src/MsfsAvionicsCommon/SimVarTypes.ts | 94 ++ .../UpdatableSimVarPublisher.ts | 13 + .../src/MsfsAvionicsCommon/common.scss | 52 + .../src/MsfsAvionicsCommon/definitions.scss | 18 + .../src/MsfsAvionicsCommon/gauges.scss | 46 + .../src/MsfsAvionicsCommon/gauges.tsx | 392 ++++++++ .../providers/DmcPublisher.tsx | 83 ++ .../providers/EgpwcBusPublisher.ts | 30 + .../providers/FGDataPublisher.ts | 16 + .../providers/FMBusPublisher.ts | 22 + .../providers/FcuBusPublisher.ts | 29 + .../providers/FmsDataPublisher.ts | 50 + .../providers/FuelSystemPublisher.ts | 53 + .../providers/SwitchableProvider.ts | 31 + .../providers/TcasBusPublisher.ts | 17 + .../providers/VorBusPublisher.ts | 134 +++ .../src/MsfsAvionicsCommon/tsconfig.json | 17 + .../systems/instruments/src/ND/.eslintrc.js | 10 + .../instruments/src/ND/FmsSymbolsPublisher.ts | 44 + .../instruments/src/ND/NDControlEvents.ts | 80 ++ .../instruments/src/ND/NDSimvarPublisher.tsx | 59 ++ .../instruments/src/ND/animations.scss | 71 ++ .../systems/instruments/src/ND/config.json | 4 + .../systems/instruments/src/ND/instrument.tsx | 172 ++++ .../src/systems/instruments/src/ND/style.scss | 141 ++- .../systems/instruments/src/ND/tsconfig.json | 34 + .../instruments/src/SD/SystemDisplay.tsx | 6 +- fbw-a380x/src/systems/tsconfig.json | 17 +- fbw-common/src/.eslintrc.js | 4 +- .../systems/instruments/src/ND/.eslintrc.js | 8 + .../src/systems/instruments/src/ND/Chrono.tsx | 1 + .../systems/instruments/src/ND/FmMessages.tsx | 15 +- .../instruments/src/ND/FmsSymbolsPublisher.ts | 13 + .../src/systems/instruments/src/ND/Layer.tsx | 29 + .../src/systems/instruments/src/ND/ND.tsx | 79 +- .../instruments/src/ND/NDControlEvents.ts | 80 ++ .../instruments/src/ND/NDSimvarPublisher.tsx | 16 + .../instruments/src/ND/TcasWxrMessages.tsx | 13 +- .../src/ND/TerrainMapThresholds.tsx | 5 +- .../instruments/src/ND/animations.scss | 71 ++ .../src/systems/instruments/src/ND/index.ts | 1 + .../instruments/src/ND/pages/NDPage.tsx | 0 .../src/ND/pages/arc/ArcModeUnderlay.tsx | 35 +- .../src/ND/pages/arc/LsCourseBug.tsx | 22 +- .../src/ND/pages/arc/LubberLine.tsx | 6 +- .../src/ND/pages/arc/SelectedHeadingBug.tsx | 20 +- .../instruments/src/ND/pages/arc/index.tsx | 21 +- .../src/ND/pages/plan/PlanModeUnderlay.tsx | 0 .../instruments/src/ND/pages/plan/index.tsx | 14 +- .../src/ND/pages/rose/Glideslope.tsx | 10 +- .../src/ND/pages/rose/IlsInfoIndicator.tsx | 15 +- .../src/ND/pages/rose/RoseLSPage.tsx | 13 +- .../src/ND/pages/rose/RoseMode.tsx | 7 +- .../src/ND/pages/rose/RoseModeUnderlay.tsx | 60 +- .../src/ND/pages/rose/RoseNavPage.tsx | 25 +- .../src/ND/pages/rose/RoseVorPage.tsx | 12 +- .../src/ND/pages/rose/VorInfoIndicator.tsx | 15 +- .../instruments/src/ND/shared/Airplane.tsx | 16 +- .../src/ND/shared/CrossTrackError.tsx | 13 +- .../instruments/src/ND/shared/Flag.tsx | 0 .../src/ND/shared/RadioNavInfo.tsx | 26 +- .../instruments/src/ND/shared/RadioNeedle.tsx | 23 +- .../instruments/src/ND/shared/TrackBug.tsx | 28 +- .../instruments/src/ND/shared/TrackLine.tsx | 16 +- .../src/ND/shared/WindIndicator.tsx | 15 +- .../instruments/src/ND/shared/common.scss | 0 .../src/ND/shared/map/CanvasMap.tsx | 22 +- .../src/ND/shared/map/ConstraintsLayer.ts | 7 +- .../src/ND/shared/map/FixInfoLayer.ts | 4 +- .../instruments/src/ND/shared/map/MapLayer.ts | 0 .../src/ND/shared/map/PaintUtils.ts | 0 .../src/ND/shared/map/PseudoWaypointLayer.ts | 9 +- .../src/ND/shared/map/RunwayLayer.ts | 4 +- .../src/ND/shared/map/TrafficLayer.ts | 7 +- .../src/ND/shared/map/WaypointLayer.ts | 4 +- .../src/ND/shared/utils/MapParameters.ts | 2 +- .../src/systems/instruments/src/ND/style.scss | 238 +++++ .../systems/instruments/src/ND/tsconfig.json | 33 + .../src/ND/types/GenericAdirsEvents.ts | 23 + .../types/GenericDisplayManagementEvents.ts | 8 + .../src/ND/types/GenericFcuEvents.ts | 11 + .../ND/types/GenericFlightGuidanceEvents.ts | 38 + .../types/GenericFlightManagementBusEvents.ts | 9 + .../src/ND/types/GenericFmsEvents.ts | 19 + .../ND/types/GenericSwitchingPanelEvents.ts | 5 + .../src/ND/types/GenericTawsEvents.ts | 12 + .../src/ND/types/GenericTcasEvents.ts | 5 + .../src/ND/types/GenericVorEvents.ts | 63 ++ .../instruments}/src/NavigationDisplay.ts | 7 +- .../src/systems/instruments/src/index.ts | 1 + .../shared/src}/Arinc429ConsumerSubject.ts | 0 .../shared/src}/Arinc429RegisterSubject.ts | 0 .../src/systems/shared/src}/ArincConsumer.ts | 0 .../src/systems/shared/src}/ArincEventBus.ts | 0 .../shared/src}/ArincEventBusSubscriber.ts | 0 .../src/systems/shared/src/FmMessages.ts | 0 .../src/systems/shared/src/MathUtils.ts | 16 + .../src/systems/shared/src/PathVector.ts | 78 ++ fbw-common/src/systems/shared/src/index.ts | 7 + 177 files changed, 3436 insertions(+), 4466 deletions(-) delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/DebugInfo.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Chrono.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/CrossTrack.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlan.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlanVectors.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/LnavStatus.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNavInfo.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNeedles.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/SpeedIndicator.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TerrainMapThresholds.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/ToWaypointIndicator.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TopMessages.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TrackLine.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Traffic.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/WindIndicator.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/FMMessages.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/NavigationDisplayMessages.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/TcasWxrMessages.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/index.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/ArcMode.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/PlanMode.tsx delete mode 100644 fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/RoseMode.tsx create mode 100644 fbw-a380x/.env create mode 100644 fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/JS/fbw-a380x/A380X_Simvars.js create mode 100644 fbw-a380x/src/systems/instruments/src/.eslintrc rename fbw-a380x/src/systems/instruments/src/Common/{CdsDisplayUnit.tsx => LegacyCdsDisplayUnit.tsx} (97%) create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/.eslintrc.js create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/CdsDisplayUnit.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/Layer.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/SimVarTypes.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UpdatableSimVarPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/common.scss create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/definitions.scss create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.scss create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FGDataPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FMBusPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/SwitchableProvider.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/TcasBusPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/VorBusPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/tsconfig.json create mode 100644 fbw-a380x/src/systems/instruments/src/ND/.eslintrc.js create mode 100644 fbw-a380x/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts create mode 100644 fbw-a380x/src/systems/instruments/src/ND/NDControlEvents.ts create mode 100644 fbw-a380x/src/systems/instruments/src/ND/NDSimvarPublisher.tsx create mode 100644 fbw-a380x/src/systems/instruments/src/ND/animations.scss create mode 100644 fbw-a380x/src/systems/instruments/src/ND/config.json create mode 100644 fbw-a380x/src/systems/instruments/src/ND/instrument.tsx rename fbw-a32nx/src/systems/instruments/src/ND_legacy/styles.scss => fbw-a380x/src/systems/instruments/src/ND/style.scss (62%) create mode 100644 fbw-a380x/src/systems/instruments/src/ND/tsconfig.json create mode 100644 fbw-common/src/systems/instruments/src/ND/.eslintrc.js rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/Chrono.tsx (99%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/FmMessages.tsx (91%) create mode 100644 fbw-common/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/Layer.tsx rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/ND.tsx (91%) create mode 100644 fbw-common/src/systems/instruments/src/ND/NDControlEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/NDSimvarPublisher.tsx rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/TcasWxrMessages.tsx (90%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/TerrainMapThresholds.tsx (94%) create mode 100644 fbw-common/src/systems/instruments/src/ND/animations.scss create mode 100644 fbw-common/src/systems/instruments/src/ND/index.ts rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/NDPage.tsx (100%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx (94%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx (78%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx (91%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx (85%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/arc/index.tsx (88%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/plan/PlanModeUnderlay.tsx (100%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/plan/index.tsx (92%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx (90%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx (91%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx (93%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx (77%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx (92%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx (85%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx (94%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx (91%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/Airplane.tsx (87%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/CrossTrackError.tsx (91%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/Flag.tsx (100%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx (94%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/RadioNeedle.tsx (92%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/TrackBug.tsx (78%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/TrackLine.tsx (83%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/WindIndicator.tsx (90%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/common.scss (100%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx (94%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts (92%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts (96%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/MapLayer.ts (100%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/PaintUtils.ts (100%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts (94%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts (97%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts (97%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts (98%) rename {fbw-a32nx => fbw-common}/src/systems/instruments/src/ND/shared/utils/MapParameters.ts (96%) create mode 100644 fbw-common/src/systems/instruments/src/ND/style.scss create mode 100644 fbw-common/src/systems/instruments/src/ND/tsconfig.json create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericAdirsEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericDisplayManagementEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericFcuEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericFlightGuidanceEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericFlightManagementBusEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericFmsEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericSwitchingPanelEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericTawsEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericTcasEvents.ts create mode 100644 fbw-common/src/systems/instruments/src/ND/types/GenericVorEvents.ts rename {fbw-a32nx/src/systems/shared => fbw-common/src/systems/instruments}/src/NavigationDisplay.ts (92%) rename {fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon => fbw-common/src/systems/shared/src}/Arinc429ConsumerSubject.ts (100%) rename {fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon => fbw-common/src/systems/shared/src}/Arinc429RegisterSubject.ts (100%) rename {fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon => fbw-common/src/systems/shared/src}/ArincConsumer.ts (100%) rename {fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon => fbw-common/src/systems/shared/src}/ArincEventBus.ts (100%) rename {fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon => fbw-common/src/systems/shared/src}/ArincEventBusSubscriber.ts (100%) rename {fbw-a32nx => fbw-common}/src/systems/shared/src/FmMessages.ts (100%) create mode 100644 fbw-common/src/systems/shared/src/PathVector.ts diff --git a/.gitignore b/.gitignore index afc7f4ff39b..e6b2590d94b 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ /fbw-a380x/.env.local !/fbw-a380x/README.md !/fbw-a380x/mach.config.js +!/fbw-a380x/.env !/fbw-a380x/docs/ !/fbw-a380x/docs/** !/fbw-a380x/src/** diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/FmsMessages.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/FmsMessages.ts index 84329a9ae3b..e36920b92ae 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/FmsMessages.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/FmsMessages.ts @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0 +import { FMMessage, FMMessageTriggers } from '@flybywiresim/fbw-sdk'; + import { RwyLsMismatchLeft, RwyLsMismatchRight } from '@fmgc/components/fms-messages/RwyLsMismatch'; import { SpecifiedNdbUnavailableLeft, SpecifiedNdbUnavailableRight } from '@fmgc/components/fms-messages/SpecifiedNdbUnavailable'; import { SpecifiedVorUnavailableLeft, SpecifiedVorUnavailableRight } from '@fmgc/components/fms-messages/SpecifiedVorUnavailable'; @@ -9,7 +11,6 @@ import { TuneNavaidLeft, TuneNavaidRight } from '@fmgc/components/fms-messages/T import { TurnAreaExceedanceLeft, TurnAreaExceedanceRight } from '@fmgc/components/fms-messages/TurnAreaExceedance'; import { FlightPlanManager } from '@shared/flightplan'; import { TdReached } from '@fmgc/components/fms-messages/TdReached'; -import { FMMessage, FMMessageTriggers } from '@shared/FmMessages'; import { StepAhead } from '@fmgc/components/fms-messages/StepAhead'; import { StepDeleted } from '@fmgc/components/fms-messages/StepDeleted'; import { FmgcComponent } from '../FmgcComponent'; diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimary.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimary.ts index 726b8890e05..b7affdbf7c6 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimary.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimary.ts @@ -1,4 +1,9 @@ -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { FMMessage, FMMessageTypes } from '@flybywiresim/fbw-sdk'; + import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; export class GpsPrimary implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimaryLost.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimaryLost.ts index ffaf75f346f..10898fa108e 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimaryLost.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/GpsPrimaryLost.ts @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0 -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { ConfirmationNode, Trigger } from '@flybywiresim/fbw-sdk'; +import { FMMessage, FMMessageTypes, ConfirmationNode, Trigger } from '@flybywiresim/fbw-sdk'; + import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; /** diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/MapPartlyDisplayed.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/MapPartlyDisplayed.ts index 8c236312253..077bc4bf400 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/MapPartlyDisplayed.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/MapPartlyDisplayed.ts @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0 -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { Trigger } from '@flybywiresim/fbw-sdk'; +import { FMMessage, FMMessageTypes, Trigger } from '@flybywiresim/fbw-sdk'; + import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; abstract class MapPartlyDisplayed implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/RwyLsMismatch.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/RwyLsMismatch.ts index 8bfe5b3e20d..3d21d511aca 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/RwyLsMismatch.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/RwyLsMismatch.ts @@ -2,9 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0 +import { FMMessage, FMMessageTypes, Trigger } from '@flybywiresim/fbw-sdk'; + import { NavaidTuner } from '@fmgc/navigation/NavaidTuner'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { Trigger } from '@flybywiresim/fbw-sdk'; import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; abstract class RwyLsMismatch implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedNdbUnavailable.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedNdbUnavailable.ts index 11eb21fbce2..e4a9d185dbe 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedNdbUnavailable.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedNdbUnavailable.ts @@ -3,8 +3,7 @@ // SPDX-License-Identifier: GPL-3.0 import { NavaidTuner } from '@fmgc/navigation/NavaidTuner'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { Trigger } from '@flybywiresim/fbw-sdk'; +import { Trigger, FMMessage, FMMessageTypes } from '@flybywiresim/fbw-sdk'; import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; abstract class SpecifiedNdbUnavailable implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedVorUnavailable.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedVorUnavailable.ts index 390a06941ad..d0980be67b5 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedVorUnavailable.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/SpecifiedVorUnavailable.ts @@ -2,9 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0 +import { Trigger, FMMessage, FMMessageTypes } from '@flybywiresim/fbw-sdk'; + import { NavaidTuner } from '@fmgc/navigation/NavaidTuner'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { Trigger } from '@flybywiresim/fbw-sdk'; import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; abstract class SpecifiedVorUnavailable implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepAhead.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepAhead.ts index d9aa38e8c5a..cd8ad79ed86 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepAhead.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepAhead.ts @@ -1,6 +1,11 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { FMMessageTypes } from '@flybywiresim/fbw-sdk'; + import { FlightPlans } from '@fmgc/flightplanning/FlightPlanManager'; import { GuidanceController } from '@fmgc/guidance/GuidanceController'; -import { FMMessageTypes } from '@shared/FmMessages'; import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; export class StepAhead implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepDeleted.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepDeleted.ts index c87df2e3d23..753c33d37a9 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepDeleted.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/StepDeleted.ts @@ -1,4 +1,9 @@ -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { FMMessage, FMMessageTypes } from '@flybywiresim/fbw-sdk'; + import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; export class StepDeleted implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TdReached.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TdReached.ts index 261e44d0649..0fb1b69e4b0 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TdReached.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TdReached.ts @@ -1,4 +1,9 @@ -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { FMMessage, FMMessageTypes } from '@flybywiresim/fbw-sdk'; + import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; export class TdReached implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TuneNavaid.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TuneNavaid.ts index 7006d6058ad..52839c2bab1 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TuneNavaid.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TuneNavaid.ts @@ -3,8 +3,7 @@ // SPDX-License-Identifier: GPL-3.0 import { NavaidTuner } from '@fmgc/navigation/NavaidTuner'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { Trigger } from '@flybywiresim/fbw-sdk'; +import { FMMessage, FMMessageTypes, Trigger } from '@flybywiresim/fbw-sdk'; import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; abstract class TuneNavaid implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TurnAreaExceedance.ts b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TurnAreaExceedance.ts index 94d8d54d6b1..0de8a0a4a92 100644 --- a/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TurnAreaExceedance.ts +++ b/fbw-a32nx/src/systems/fmgc/src/components/fms-messages/TurnAreaExceedance.ts @@ -2,11 +2,11 @@ // // SPDX-License-Identifier: GPL-3.0 +import { FMMessage, FMMessageTypes, Trigger } from '@flybywiresim/fbw-sdk'; + import { GuidanceController } from '@fmgc/guidance/GuidanceController'; import { PILeg } from '@fmgc/guidance/lnav/legs/PI'; import { Navigation } from '@fmgc/navigation/Navigation'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { Trigger } from '@flybywiresim/fbw-sdk'; import { FMMessageSelector, FMMessageUpdate } from './FmsMessages'; abstract class TurnAreaExceedance implements FMMessageSelector { diff --git a/fbw-a32nx/src/systems/fmgc/src/efis/EfisCommon.ts b/fbw-a32nx/src/systems/fmgc/src/efis/EfisCommon.ts index 1a5e4aa3a1a..7b75608b8a7 100644 --- a/fbw-a32nx/src/systems/fmgc/src/efis/EfisCommon.ts +++ b/fbw-a32nx/src/systems/fmgc/src/efis/EfisCommon.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0 -import { EfisNdMode, EfisNdRangeValue } from '@shared/NavigationDisplay'; +import { EfisNdMode, EfisNdRangeValue } from '@flybywiresim/fbw-sdk'; import { Coordinates } from '@fmgc/flightplanning/data/geo'; export function withinEditArea(lla: Coordinates, range: EfisNdRangeValue, mode: EfisNdMode, planCentre: Coordinates, trueHeading: DegreesTrue): boolean { diff --git a/fbw-a32nx/src/systems/fmgc/src/efis/EfisSymbols.ts b/fbw-a32nx/src/systems/fmgc/src/efis/EfisSymbols.ts index 9ed95ebcfbc..e33ac4a2c06 100644 --- a/fbw-a32nx/src/systems/fmgc/src/efis/EfisSymbols.ts +++ b/fbw-a32nx/src/systems/fmgc/src/efis/EfisSymbols.ts @@ -3,10 +3,12 @@ // // SPDX-License-Identifier: GPL-3.0 -import { GenericDataListenerSync, LegType, RunwaySurface, TurnDirection, VorType } from '@flybywiresim/fbw-sdk'; +import { + GenericDataListenerSync, LegType, RunwaySurface, TurnDirection, VorType, EfisOption, EfisNdMode, NdSymbol, NdSymbolTypeFlags, EfisNdRangeValue, + efisRangeSettings, +} from '@flybywiresim/fbw-sdk'; import { FlightPlanManager, WaypointConstraintType } from '@fmgc/flightplanning/FlightPlanManager'; -import { EfisOption, EfisNdMode, NdSymbol, NdSymbolTypeFlags, EfisNdRangeValue, rangeSettings } from '@shared/NavigationDisplay'; import { GuidanceManager } from '@fmgc/guidance/GuidanceManager'; import { Coordinates } from '@fmgc/flightplanning/data/geo'; import { GuidanceController } from '@fmgc/guidance/GuidanceController'; @@ -124,7 +126,7 @@ export class EfisSymbols { }; for (const side of EfisSymbols.sides) { - const range = rangeSettings[SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_ND_RANGE`, 'number')]; + const range = efisRangeSettings[SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_ND_RANGE`, 'number')]; const mode: EfisNdMode = SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_ND_MODE`, 'number'); const efisOption = SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_OPTION`, 'Enum'); diff --git a/fbw-a32nx/src/systems/fmgc/src/efis/EfisVectors.ts b/fbw-a32nx/src/systems/fmgc/src/efis/EfisVectors.ts index 95ed384f732..76f1b33323e 100644 --- a/fbw-a32nx/src/systems/fmgc/src/efis/EfisVectors.ts +++ b/fbw-a32nx/src/systems/fmgc/src/efis/EfisVectors.ts @@ -3,12 +3,12 @@ // // SPDX-License-Identifier: GPL-3.0 +import { EfisSide, EfisVectorsGroup, GenericDataListenerSync } from '@flybywiresim/fbw-sdk'; + import { GuidanceController } from '@fmgc/guidance/GuidanceController'; -import { EfisSide, EfisVectorsGroup } from '@shared/NavigationDisplay'; import { PathVector, pathVectorLength, pathVectorValid } from '@fmgc/guidance/lnav/PathVector'; import { LnavConfig } from '@fmgc/guidance/LnavConfig'; import { ArmedLateralMode, isArmed, LateralMode } from '@shared/autopilot'; -import { GenericDataListenerSync } from '@flybywiresim/fbw-sdk'; const UPDATE_TIMER = 2_500; diff --git a/fbw-a32nx/src/systems/fmgc/src/guidance/FmsState.ts b/fbw-a32nx/src/systems/fmgc/src/guidance/FmsState.ts index c1a2a51494d..c2d917117c7 100644 --- a/fbw-a32nx/src/systems/fmgc/src/guidance/FmsState.ts +++ b/fbw-a32nx/src/systems/fmgc/src/guidance/FmsState.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0 -import { EfisNdMode, EfisNdRangeValue } from '@shared/NavigationDisplay'; +import { EfisNdMode, EfisNdRangeValue } from '@flybywiresim/fbw-sdk'; export interface FmsState { leftEfisState: EfisState, diff --git a/fbw-a32nx/src/systems/fmgc/src/guidance/GuidanceController.ts b/fbw-a32nx/src/systems/fmgc/src/guidance/GuidanceController.ts index 938994c1ec4..ba9570e7831 100644 --- a/fbw-a32nx/src/systems/fmgc/src/guidance/GuidanceController.ts +++ b/fbw-a32nx/src/systems/fmgc/src/guidance/GuidanceController.ts @@ -3,16 +3,16 @@ // // SPDX-License-Identifier: GPL-3.0 +import { EfisSide, EfisNdMode, efisRangeSettings, SimVarString } from '@flybywiresim/fbw-sdk'; + import { Geometry } from '@fmgc/guidance/Geometry'; import { PseudoWaypoint } from '@fmgc/guidance/PseudoWaypoint'; import { PseudoWaypoints } from '@fmgc/guidance/lnav/PseudoWaypoints'; import { EfisVectors } from '@fmgc/efis/EfisVectors'; import { Coordinates } from '@fmgc/flightplanning/data/geo'; import { EfisState } from '@fmgc/guidance/FmsState'; -import { EfisSide, EfisNdMode, rangeSettings } from '@shared/NavigationDisplay'; import { TaskCategory, TaskQueue } from '@fmgc/guidance/TaskQueue'; import { HMLeg } from '@fmgc/guidance/lnav/legs/HX'; -import { SimVarString } from '@flybywiresim/fbw-sdk'; import { getFlightPhaseManager } from '@fmgc/flightphase'; import { FmgcFlightPhase } from '@shared/flightphase'; import { VerticalProfileComputationParametersObserver } from '@fmgc/guidance/vnav/VerticalProfileComputationParameters'; @@ -124,7 +124,7 @@ export class GuidanceController { private updateEfisState(side: EfisSide, state: EfisState): void { const ndMode = SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_ND_MODE`, 'Enum') as EfisNdMode; - const ndRange = rangeSettings[SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_ND_RANGE`, 'Enum')]; + const ndRange = efisRangeSettings[SimVar.GetSimVarValue(`L:A32NX_EFIS_${side}_ND_RANGE`, 'Enum')]; if (state?.mode !== ndMode || state?.range !== ndRange) { this.taskQueue.cancelAllInCategory(TaskCategory.EfisVectors); diff --git a/fbw-a32nx/src/systems/fmgc/src/guidance/lnav/PseudoWaypoints.ts b/fbw-a32nx/src/systems/fmgc/src/guidance/lnav/PseudoWaypoints.ts index 4ea6b716cf7..ee198c86d26 100644 --- a/fbw-a32nx/src/systems/fmgc/src/guidance/lnav/PseudoWaypoints.ts +++ b/fbw-a32nx/src/systems/fmgc/src/guidance/lnav/PseudoWaypoints.ts @@ -6,7 +6,7 @@ import { GuidanceComponent } from '@fmgc/guidance/GuidanceComponent'; import { PseudoWaypoint, PseudoWaypointFlightPlanInfo, PseudoWaypointSequencingAction } from '@fmgc/guidance/PseudoWaypoint'; import { VnavConfig, VnavDescentMode } from '@fmgc/guidance/vnav/VnavConfig'; -import { NdSymbolTypeFlags } from '@shared/NavigationDisplay'; +import { NdSymbolTypeFlags } from '@flybywiresim/fbw-sdk'; import { Geometry } from '@fmgc/guidance/Geometry'; import { Coordinates } from '@fmgc/flightplanning/data/geo'; import { GuidanceController } from '@fmgc/guidance/GuidanceController'; diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx index fca53ebe79a..f10f8141b5f 100644 --- a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx @@ -1,7 +1,11 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { SimVarValueType } from '@microsoft/msfs-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; +import { ArincEventBus, EfisSide } from '@flybywiresim/fbw-sdk'; + import { AdirsSimVars, SwitchingPanelVSimVars } from './SimVarTypes'; -import { ArincEventBus } from './ArincEventBus'; import { UpdatableSimVarPublisher } from './UpdatableSimVarPublisher'; export class AdirsValueProvider { diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx index 9c3cfe69c13..ac25ee2862c 100644 --- a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx @@ -3,8 +3,7 @@ // SPDX-License-Identifier: GPL-3.0 import { EventBus, SimVarDefinition, SimVarPublisher, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; -import { Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { Arinc429RegisterSubject } from '../Arinc429RegisterSubject'; +import { Arinc429WordData, Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; import { AdirsSimVars } from '../SimVarTypes'; export interface DmcLogicEvents { diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts index e714dda37e7..58be7046ada 100644 --- a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts @@ -1,5 +1,9 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; +import { EfisSide } from '@flybywiresim/fbw-sdk'; export enum TerrainLevelMode { PeaksMode = 0, diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts index 7f133a6f28f..29f9678db84 100644 --- a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts +++ b/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts @@ -1,5 +1,9 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; -import { EfisNdMode, EfisOption, EfisSide, NavAidMode } from '@shared/NavigationDisplay'; +import { EfisNdMode, EfisOption, EfisSide, NavAidMode } from '@flybywiresim/fbw-sdk'; export interface FcuSimVars { ndRangeSetting: number, diff --git a/fbw-a32nx/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts b/fbw-a32nx/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts index 44e85609eb6..6c073793be7 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts +++ b/fbw-a32nx/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts @@ -3,9 +3,9 @@ // SPDX-License-Identifier: GPL-3.0 import { BasePublisher, EventBus } from '@microsoft/msfs-sdk'; -import { EfisSide, NdSymbol, NdTraffic } from '@shared/NavigationDisplay'; +import { EfisSide, NdSymbol, NdTraffic, GenericDataListenerSync } from '@flybywiresim/fbw-sdk'; + import { PathVector } from '@fmgc/guidance/lnav/PathVector'; -import { GenericDataListenerSync } from '@flybywiresim/fbw-sdk'; export interface FmsSymbolsData { symbols: NdSymbol[], diff --git a/fbw-a32nx/src/systems/instruments/src/ND/NDControlEvents.ts b/fbw-a32nx/src/systems/instruments/src/ND/NDControlEvents.ts index 30623ba2ebd..f35c8bd11ee 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/NDControlEvents.ts +++ b/fbw-a32nx/src/systems/instruments/src/ND/NDControlEvents.ts @@ -1,7 +1,11 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + /** * Events for internal ND communication between components */ -import { EfisNdMode } from '@shared/NavigationDisplay'; +import { EfisNdMode } from '@flybywiresim/fbw-sdk'; export interface NDControlEvents { /** diff --git a/fbw-a32nx/src/systems/instruments/src/ND/instrument.tsx b/fbw-a32nx/src/systems/instruments/src/ND/instrument.tsx index ad9e19d919e..29eb2c2487f 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/instrument.tsx +++ b/fbw-a32nx/src/systems/instruments/src/ND/instrument.tsx @@ -1,6 +1,11 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { Clock, FsBaseInstrument, FSComponent, FsInstrument, HEventPublisher, InstrumentBackplane, Subject } from '@microsoft/msfs-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; -import { NDComponent } from './ND'; +import { ArincEventBus, EfisSide } from '@flybywiresim/fbw-sdk'; +import { NDComponent } from '@flybywiresim/navigation-display'; + import { NDSimvarPublisher, NDSimvars } from './NDSimvarPublisher'; import { AdirsValueProvider } from '../MsfsAvionicsCommon/AdirsValueProvider'; import { FmsDataPublisher } from '../MsfsAvionicsCommon/providers/FmsDataPublisher'; @@ -9,11 +14,10 @@ import { VorBusPublisher } from '../MsfsAvionicsCommon/providers/VorBusPublisher import { TcasBusPublisher } from '../MsfsAvionicsCommon/providers/TcasBusPublisher'; import { FGDataPublisher } from '../MsfsAvionicsCommon/providers/FGDataPublisher'; import { NDControlEvents } from './NDControlEvents'; -import { getDisplayIndex } from '../MsfsAvionicsCommon/displayUnit'; +import { DisplayUnit, getDisplayIndex } from '../MsfsAvionicsCommon/displayUnit'; import { EgpwcBusPublisher } from '../MsfsAvionicsCommon/providers/EgpwcBusPublisher'; import { DmcPublisher } from '../MsfsAvionicsCommon/providers/DmcPublisher'; import { FMBusPublisher } from '../MsfsAvionicsCommon/providers/FMBusPublisher'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; import { FcuBusPublisher } from '../MsfsAvionicsCommon/providers/FcuBusPublisher'; import './style.scss'; @@ -53,6 +57,12 @@ class NDInstrument implements FsInstrument { private readonly clock: Clock; + private displayBrightness = Subject.create(0); + + private displayFailed = Subject.create(false); + + private displayPowered = Subject.create(false); + constructor() { const side: EfisSide = getDisplayIndex() === 1 ? 'L' : 'R'; const stateSubject = Subject.create<'L' | 'R'>(side); @@ -99,7 +109,24 @@ class NDInstrument implements FsInstrument { this.adirsValueProvider.start(); - FSComponent.render(, document.getElementById('ND_CONTENT')); + const sub = this.bus.getSubscriber(); + + const isCaptainSide = getDisplayIndex() === 1; + + sub.on(isCaptainSide ? 'potentiometerCaptain' : 'potentiometerFo').whenChanged().handle((value) => { + this.displayBrightness.set(value); + }); + + sub.on(isCaptainSide ? 'elec' : 'elecFo').whenChanged().handle((value) => { + this.displayPowered.set(value); + }); + + FSComponent.render( + + + , + document.getElementById('ND_CONTENT'), + ); // Remove "instrument didn't load" text document.getElementById('ND_CONTENT').querySelector(':scope > h1').remove(); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/tsconfig.json b/fbw-a32nx/src/systems/instruments/src/ND/tsconfig.json index 2d56720368e..a66548247a2 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/tsconfig.json +++ b/fbw-a32nx/src/systems/instruments/src/ND/tsconfig.json @@ -27,7 +27,8 @@ "@shared/*": ["./shared/src/*"], "@tcas/*": ["./tcas/src/*"], "@typings/*": ["../../../fbw-common/src/typings/*"], - "@flybywiresim/fbw-sdk": ["../../../fbw-common/src/systems/index-no-react.ts"] + "@flybywiresim/fbw-sdk": ["../../../fbw-common/src/systems/index-no-react.ts"], + "@flybywiresim/navigation-display": ["../../../fbw-common/src/systems/instruments/src/ND/index.ts"] } } } diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/DebugInfo.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/DebugInfo.tsx deleted file mode 100644 index 231dd093bae..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/DebugInfo.tsx +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React from 'react'; -import { Layer, useSimVar } from '@flybywiresim/fbw-sdk'; -import { ControlLaw } from '@fmgc/guidance/ControlLaws'; -import { useCurrentFlightPlan } from '@instruments/common/flightplan'; - -export const DebugInfo: React.FC = () => { - const [law] = useSimVar('L:A32NX_FG_CURRENT_LATERAL_LAW', 'number', 1_000); - const [xte] = useSimVar('L:A32NX_FG_CROSS_TRACK_ERROR', 'number', 100); - const [tae] = useSimVar('L:A32NX_FG_TRACK_ANGLE_ERROR', 'number', 100); - const [phi] = useSimVar('L:A32NX_FG_PHI_COMMAND', 'number', 100); - - return ( - - debug - - - law: - {' '} - {law} - {' '} - {ControlLaw[law]} - - - xte: - {' '} - {xte} - - - tae: - {' '} - {tae} - - - phi: - {' '} - {phi} - - - - - ); -}; - -const DebugLegs: React.FC = () => { - const currentFlightPlan = useCurrentFlightPlan(); - - return ( - <> - {currentFlightPlan.waypoints.map((waypoint: WayPoint, index) => {waypoint.ident})} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Chrono.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Chrono.tsx deleted file mode 100644 index 629c0d3a25f..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Chrono.tsx +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { useEffect, useState } from 'react'; -import { useInteractionEvent, useSimVar } from '@flybywiresim/fbw-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; -import { debouncedTimeDelta } from '../../Common'; - -// TODO need a font with the right H ' and " chars - -const getDisplayString = (seconds: number) : string => { - if (seconds >= 3600) { - return `${Math.floor(seconds / 3600).toString().padStart(2, '0')}H${Math.floor((seconds % 3600) / 60).toString().padStart(2, '0')}'`; - } - return `${Math.floor(seconds / 60).toString().padStart(2, '0')}'${Math.floor(seconds % 60).toString().padStart(2, '0')}"`; -}; - -export const Chrono: React.FC<{ side: EfisSide }> = ({ side }) => { - const [absTime] = useSimVar('E:ABSOLUTE TIME', 'Seconds', 200); - const [prevTime, setPrevTime] = useState(absTime); - - const [elapsedTime, setElapsedTime] = useState(0); - const [state, setState] = useState('HIDDEN'); - - useEffect(() => { - if (state === 'RUNNING') { - // max 99 hours, 59 min - setElapsedTime( - Math.min(359940, elapsedTime + debouncedTimeDelta(absTime, prevTime)), - ); - } - setPrevTime(absTime); - }, [absTime]); - - useInteractionEvent(`A32NX_EFIS_${side}_CHRONO_PUSHED`, () => { - switch (state) { - case 'HIDDEN': - setPrevTime(absTime); - setElapsedTime(0); - setState('RUNNING'); - break; - case 'RUNNING': - setState('STOPPED'); - break; - case 'STOPPED': - setState('HIDDEN'); - break; - default: - } - }); - - if (state === 'HIDDEN') { - return <>; - } - return ( - - - {getDisplayString(elapsedTime)} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/CrossTrack.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/CrossTrack.tsx deleted file mode 100644 index a18f64804ea..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/CrossTrack.tsx +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import { useSimVar } from '@flybywiresim/fbw-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; -import React from 'react'; - -interface CrossTrackProps { - x: number, - y: number, - isPlanMode?: boolean, - side: EfisSide, -} - -export const CrossTrack: React.FC = ({ x, y, isPlanMode, side }) => { - const [crossTrackError] = useSimVar('L:A32NX_FG_CROSS_TRACK_ERROR', 'nautical miles', 250); - const [rnp] = useSimVar(`L:A32NX_FMGC_${side}_RNP`, 'number'); - - let crossTrackText = ''; - let crossTrackAnchor = 'start'; - let crossTrackX = x; - const crossTrackAbs = Math.min(99.9, Math.abs(crossTrackError)); - - if (rnp > 0 && rnp < 0.305 && crossTrackAbs > 0.0195 && crossTrackAbs < 0.295) { - crossTrackText = crossTrackAbs.toFixed(2); - } else if (crossTrackAbs >= 0.1) { - crossTrackText = crossTrackAbs.toFixed(1); - } - - if (crossTrackText.length > 0) { - if (crossTrackError < 0) { - crossTrackText += 'R'; - crossTrackAnchor = 'start'; - crossTrackX = x + 34; - } else { - crossTrackText += 'L'; - crossTrackAnchor = 'end'; - crossTrackX = x - 38; - } - } - - return ( - - {crossTrackText} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlan.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlan.tsx deleted file mode 100644 index 01171e404c1..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlan.tsx +++ /dev/null @@ -1,571 +0,0 @@ -// Copyright (c) 2021 FlyByWire Simulations -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, memo } from 'react'; -import { MathUtils, useSimVar, Layer } from '@flybywiresim/fbw-sdk'; -import { TFLeg } from '@fmgc/guidance/lnav/legs/TF'; -import { VMLeg } from '@fmgc/guidance/lnav/legs/VM'; -import { EfisSide, EfisVectorsGroup, NdSymbol, NdSymbolTypeFlags } from '@shared/NavigationDisplay'; -import { Leg } from '@fmgc/guidance/lnav/legs/Leg'; -import { HALeg, HFLeg, HMLeg, HxLegGuidanceState } from '@fmgc/guidance/lnav/legs/HX'; -import { MapParameters } from '../utils/MapParameters'; -import { FlightPlanVectors } from './FlightPlanVectors'; - -export enum FlightPlanType { - Nav, - Dashed, - Temp -} - -export type FlightPathProps = { - x?: number, - y?: number, - side: EfisSide, - range: number, - symbols: NdSymbol[], - mapParams: MapParameters, - mapParamsVersion: number, - debug: boolean, -} - -export const FlightPlan: FC = memo(({ x = 0, y = 0, side, range, symbols, mapParams }) => { - if (!mapParams.valid) { - return null; - } - - return ( - - { /* constraint circles need to be drawn under the flight path */ } - {symbols.filter((symbol) => (symbol.type & NdSymbolTypeFlags.Constraint) > 0).map((symbol) => { - const position = mapParams.coordinatesToXYy(symbol.location); - - return ( - - ); - })} - - {Object.keys(EfisVectorsGroup).filter((it) => !Number.isNaN(parseInt(it))).map((group) => ( - - ))} - - {symbols.map((symbol) => { - if (!symbol.location) { - return false; - } - - const position = mapParams.coordinatesToXYy(symbol.location); - - return ( - - ); - })} - - ); -}); - -const VorMarker: FC<{ colour: string }> = ({ colour }) => ( - <> - - - - - -); - -const VorDmeMarker: FC<{ colour: string }> = ({ colour }) => ( - <> - - - - - - - - - - - -); - -const DmeMarker: FC<{ colour: string }> = ({ colour }) => ( - <> - - - -); - -const NdbMarker: FC<{ colour: string }> = ({ colour }) => ( - <> - - - -); - -const WaypointMarker: FC<{ colour: string }> = ({ colour }) => ( - <> - - - -); - -const AirportMarker: FC<{ colour: string }> = ({ colour }) => ( - <> - - - - - - - - - -); - -const RunwayIdent: FC<{ ident: string, rotation: number }> = ({ ident, rotation }) => { - const airportIdent = ident.substring(0, 4); - const runwayIdent = ident.substring(4); - - return ( - - - {airportIdent} - - - {runwayIdent.padEnd(4, '\xa0')} - - - ); -}; - -interface RunwayMarkerProps { - ident: string, - mapParams: MapParameters, - direction: number, - lengthPx: number, -} - -const RunwayMarkerClose: FC = memo(({ ident, mapParams, direction, lengthPx }) => { - useSimVar('PLANE HEADING DEGREES TRUE', 'number'); - - const rotation = mapParams.rotation(direction); - - return ( - - - - - - - - ); -}); - -const RunwayMarkerFar: FC> = memo(({ ident, mapParams, direction }) => { - useSimVar('PLANE HEADING DEGREES TRUE', 'number'); - - const rotation = mapParams.rotation(direction); - - return ( - - - - - - ); -}); - -interface CourseReversalMarkerProps { - mapParams: MapParameters, - left: boolean, - direction: number, -} -const CourseReversalMarker: FC = memo(({ mapParams, left, direction }) => { - useSimVar('PLANE HEADING DEGREES TRUE', 'number'); - - const rotation = mapParams.rotation(direction); - const arcEnd = left ? -42 : 42; - return ( - - - - - - - - - ); -}); - -interface SymbolMarkerProps { - ident: string, - x: number, - y: number, - type: NdSymbolTypeFlags, - constraints?: string[], - length?: number, - direction?: number, - radials?: number[], - radii?: number[], - mapParams: MapParameters, - ndRange: number, -} - -export const SymbolMarker: FC = memo(({ ident, x, y, type, constraints, length, direction, radials, radii, mapParams, ndRange }) => { - let colour = 'White'; - let shadow = true; - // todo airport as well if in flightplan - if (type & NdSymbolTypeFlags.Runway) { - colour = 'White'; - } else if (type & NdSymbolTypeFlags.ActiveLegTermination) { - colour = 'White'; - } else if (type & NdSymbolTypeFlags.Tuned) { - colour = 'Cyan'; - } else if (type & (NdSymbolTypeFlags.FlightPlan | NdSymbolTypeFlags.FixInfo)) { - colour = 'Green'; - } else if (type & NdSymbolTypeFlags.EfisOption) { - colour = 'Magenta'; - shadow = false; - } - - const elements: JSX.Element[] = []; - - // FIX INFO - if (type & NdSymbolTypeFlags.FixInfo) { - if (radii !== undefined) { - for (const radius of radii) { - const radiusPx = radius * mapParams.nmToPx; - elements.push( - , - ); - elements.push( - , - ); - } - } - - if (radials !== undefined) { - for (const bearing of radials) { - const rotation = mapParams.rotation(bearing) * Math.PI / 180; - // TODO how long should a piece of string be? - const x2 = Math.sin(rotation) * 9000; - const y2 = -Math.cos(rotation) * 9000; - elements.push(); - elements.push(); - } - } - } - - if (constraints) { - let constraintY = 17; - elements.push(...constraints.map((t) => ( - {t} - ))); - } - - if (type & (NdSymbolTypeFlags.CourseReversalLeft | NdSymbolTypeFlags.CourseReversalRight)) { - elements.push( 0} direction={direction!} />); - } - - let showIdent = false; - const identYOffset = 0; - if (type & NdSymbolTypeFlags.VorDme) { - elements.push(); - showIdent = true; - } else if (type & NdSymbolTypeFlags.Vor) { - elements.push(); - showIdent = true; - } else if (type & NdSymbolTypeFlags.Dme) { - elements.push(); - showIdent = true; - } else if (type & NdSymbolTypeFlags.Ndb) { - elements.push(); - showIdent = true; - } else if (type & NdSymbolTypeFlags.Runway) { - if (ndRange > 80) { - elements.push(); - } else { - elements.push(); - } - } else if (type & NdSymbolTypeFlags.Airport) { - showIdent = true; - elements.push(); - } else if (type & (NdSymbolTypeFlags.Waypoint | NdSymbolTypeFlags.FlightPlan | NdSymbolTypeFlags.FixInfo)) { - showIdent = true; - elements.push(); - } else if (type & (NdSymbolTypeFlags.PwpTopOfDescent)) { - showIdent = false; - elements.push( - <> - - - - , - ); - } else if (type & (NdSymbolTypeFlags.PwpCdaFlap1)) { - showIdent = false; - elements.push( - <> - - - - 1 - , - ); - } else if (type & (NdSymbolTypeFlags.PwpCdaFlap2)) { - showIdent = false; - elements.push( - <> - - - - 2 - , - ); - } else if (type & (NdSymbolTypeFlags.PwpDecel)) { - showIdent = false; - elements.push( - <> - - - - D - , - ); - } else if (type & (NdSymbolTypeFlags.PwpClimbLevelOff)) { - showIdent = false; - elements.push( - <> - - - - , - ); - } else if (type & (NdSymbolTypeFlags.PwpDescentLevelOff)) { - showIdent = false; - elements.push( - <> - - - - , - ); - } else if (type & (NdSymbolTypeFlags.PwpStartOfClimb)) { - showIdent = false; - elements.push( - <> - - - - , - ); - } else if (type & (NdSymbolTypeFlags.PwpInterceptProfile)) { - showIdent = false; - elements.push( - <> - - - - , - ); - } else if (type & (NdSymbolTypeFlags.PwpTimeMarker)) { - colour = 'Green'; - showIdent = true; - elements.push( - <> - - - , - ); - } else if (type & (NdSymbolTypeFlags.PwpSpeedChange)) { - showIdent = false; - elements.push( - , - ); - } - - if (showIdent) { - elements.push( - - {ident} - , - ); - } - - return ( - - {elements} - - ); -}); - -interface ConstraintMarkerProps { - x: number, - y: number, - type: NdSymbolTypeFlags, -} - -export const ConstraintMarker: FC = memo(({ x, y, type }) => ( - - - - -)); - -export type DebugLegProps = { - leg: TLeg, - mapParams: MapParameters, -}; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const DebugLeg: FC> = ({ leg, mapParams }) => { - if (leg instanceof TFLeg) { - return ; - } if (leg instanceof VMLeg) { - return ; - } if (leg instanceof HALeg || leg instanceof HFLeg || leg instanceof HMLeg) { - return ; - } - - return null; -}; - -const DebugTFLeg: FC> = ({ leg, mapParams }) => { - const legType = 'TF'; - - const [lat] = useSimVar('PLANE LATITUDE', 'degrees', 250); - const [long] = useSimVar('PLANE LONGITUDE', 'degrees', 250); - - const [fromX, fromY] = mapParams.coordinatesToXYy(leg.from.infos.coordinates); - const [toX, toY] = mapParams.coordinatesToXYy(leg.to.infos.coordinates); - - const [infoX, infoY] = [ - Math.round(Math.min(fromX, toX) + (Math.abs(toX - fromX) / 2) + 5), - Math.round(Math.min(fromY, toY) + (Math.abs(toY - fromY) / 2)), - ]; - - return ( - <> - - {leg.from.ident} - {' '} - -> - {' '} - {leg.to.ident} - - {legType} - - Tl: - {' '} - {MathUtils.fastToFixed(leg.inboundCourse, 1)} - - - tA: - {' '} - {MathUtils.fastToFixed(leg.getAircraftToLegBearing({ lat, long }), 1)} - - - DTG: - {' '} - {MathUtils.fastToFixed(leg.getDistanceToGo({ lat, long }), 3)} - - - ); -}; - -const DebugVMLeg: FC> = ({ leg, mapParams }) => { - const legType = 'VM'; - - const [lat] = useSimVar('PLANE LATITUDE', 'degrees', 250); - const [long] = useSimVar('PLANE LONGITUDE', 'degrees', 250); - - const [fromX, fromY] = mapParams.coordinatesToXYy({ lat, long }); - - const [infoX, infoY] = [fromX, fromY - 150]; - - return ( - <> - - {leg.heading} - ° - - {legType} - - ); -}; - -const DebugHXLeg: FC> = ({ leg, mapParams }) => { - const legType = leg.constructor.name.substr(0, 2); - - const [fromX, fromY] = mapParams.coordinatesToXYy(leg.to.infos.coordinates); - - const [infoX, infoY] = [fromX, fromY - 150]; - - return ( - <> - - {HxLegGuidanceState[leg.state]} - {' - r='} - {leg.radius.toFixed(1)} - {' NM'} - - {legType} - - ); -}; - -const typeFlagToColor = (typeFlag: NdSymbolTypeFlags) => { - if (typeFlag & NdSymbolTypeFlags.CyanColor) { - return 'Cyan'; - } if (typeFlag & NdSymbolTypeFlags.MagentaColor) { - return 'Magenta'; - } if (typeFlag & NdSymbolTypeFlags.AmberColor) { - return 'Amber'; - } - - return 'White'; -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlanVectors.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlanVectors.tsx deleted file mode 100644 index 18ada7bd04d..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/FlightPlanVectors.tsx +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, memo, useCallback, useState } from 'react'; -import { Layer, useFlowSyncEvent } from '@flybywiresim/fbw-sdk'; -import { DebugPointColour, PathVector, PathVectorType } from '@fmgc/guidance/lnav/PathVector'; -import { LnavConfig } from '@fmgc/guidance/LnavConfig'; -import { EfisSide, EfisVectorsGroup } from '@shared/NavigationDisplay'; -import { MapParameters } from '../utils/MapParameters'; - -export interface FlightPlanVectorsProps { - x: number, - y: number, - mapParams: MapParameters, - mapParamsVersion: number, - side: EfisSide, - group: EfisVectorsGroup, -} - -/** - * Receives and draws EFIS vectors for a certain vector group (flight plan) - */ -export const FlightPlanVectors: FC = memo(({ x, y, mapParams, side, group }) => { - const [vectors, setVectors] = useState([]); - - const lineStyle = vectorsGroupLineStyle(group); - - useFlowSyncEvent(`A32NX_EFIS_VECTORS_${side}_${EfisVectorsGroup[group]}`, useCallback((_topic, data) => { - if (data) { - setVectors(data); - } else if (LnavConfig.DEBUG_PATH_DRAWING) { - console.warn(`[ND/Vectors] Received falsy vectors on event '${EfisVectorsGroup[group]}'.`); - } - }, [group])); - - return ( - - {vectors.filter((vector) => isVectorValid(vector)).map((vector, index) => { - switch (vector.type) { - case PathVectorType.Line: - const [sx, sy] = mapParams.coordinatesToXYy(vector.startPoint); - const [ex, ey] = mapParams.coordinatesToXYy(vector.endPoint); - - return ( - - ); - case PathVectorType.Arc: - const [ix, iy] = mapParams.coordinatesToXYy(vector.startPoint); - const [fx, fy] = mapParams.coordinatesToXYy(vector.endPoint); - - // TODO msfs-geo when it has planar calcs - const radius = Avionics.Utils.computeDistance(vector.centrePoint, vector.endPoint) * mapParams.nmToPx; - - return ( - 180 ? 1 : 0} ${vector.sweepAngle > 0 ? 1 : 0} ${fx} ${fy}`} - /> - ); - case PathVectorType.DebugPoint: - const [x, y] = mapParams.coordinatesToXYy(vector.startPoint); - - const offset = index % 2 === 0; - - const colour = DebugPointColour[vector.colour ?? DebugPointColour.Cyan]; - - return ( - <> - - - {vector.annotation} - - ); - default: - return null; - } - })} - - ); -}); - -function isVectorValid(vector: PathVector): boolean { - if (!vector) { - return false; - } - - if (vector.type === null || vector.type === undefined) { - return false; - } - - switch (vector.type) { - case PathVectorType.Line: - return !!vector.startPoint; - case PathVectorType.Arc: - return !!vector.startPoint && !!vector.centrePoint && !!vector.endPoint; - case PathVectorType.DebugPoint: - return !!vector.startPoint; - default: - return false; - } -} - -function vectorsGroupLineStyle(group: EfisVectorsGroup): React.SVGAttributes { - switch (group) { - case EfisVectorsGroup.ACTIVE: - return { stroke: '#0f0' }; - case EfisVectorsGroup.DASHED: - case EfisVectorsGroup.OFFSET: - return { stroke: '#0f0', strokeDasharray: '15 12' }; - case EfisVectorsGroup.TEMPORARY: - return { stroke: '#ff0', strokeDasharray: '15 12' }; - case EfisVectorsGroup.SECONDARY: - return { stroke: '#888' }; - case EfisVectorsGroup.SECONDARY_DASHED: - return { stroke: '#888', strokeDasharray: '15 12' }; - case EfisVectorsGroup.MISSED: - return { stroke: '#0ff' }; - case EfisVectorsGroup.ALTERNATE: - return { stroke: '#0ff', strokeDasharray: '15 12' }; - case EfisVectorsGroup.ACTIVE_EOSID: - return { stroke: '#ff0' }; - default: - return { stroke: '#f00' }; - } -} diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/LnavStatus.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/LnavStatus.tsx deleted file mode 100644 index a777a1f9452..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/LnavStatus.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, useState } from 'react'; -import { useCoherentEvent, Layer } from '@flybywiresim/fbw-sdk'; - -export const LnavStatus: FC = () => { - const [strings, setStrings] = useState([]); - - useCoherentEvent('A32NX_FM_DEBUG_LNAV_STATUS', (message: string) => { - setStrings(message.split('\n')); - }); - - return ( - - {strings.map((line, i) => ( - {line} - ))} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNavInfo.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNavInfo.tsx deleted file mode 100644 index a2899500f7d..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNavInfo.tsx +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { useEffect, useState } from 'react'; -import { useSimVar, useArinc429Var } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, EfisSide, NavAidMode } from '@shared/NavigationDisplay'; - -export type RadioNavInfoProps = { - index: 1 | 2, - side: EfisSide, - trueRef: boolean, - mode: EfisNdMode, -} - -const TuningModeIndicator: React.FC<{ index: 1 | 2, adf?: boolean }> = ({ index, adf = false }) => { - const [fm1Healthy] = useSimVar('L:A32NX_FM1_HEALTHY_DISCRETE', 'boolean'); - const [fm2Healthy] = useSimVar('L:A32NX_FM2_HEALTHY_DISCRETE', 'boolean'); - const fm1NavDiscrete = useArinc429Var('L:A32NX_FM1_NAV_DISCRETE'); - const fm2NavDiscrete = useArinc429Var('L:A32NX_FM2_NAV_DISCRETE'); - const [tuningMode, setTuningMode] = useState(''); - - useEffect(() => { - const bitIndex = 10 + index + (adf ? 2 : 0); - if ((!fm1Healthy && !fm2Healthy) || (!fm1NavDiscrete.isNormalOperation() && !fm2NavDiscrete.isNormalOperation())) { - setTuningMode('R'); - } else if (fm1NavDiscrete.getBitValueOr(bitIndex, false) || fm2NavDiscrete.getBitValueOr(bitIndex, false)) { - setTuningMode('M'); - } else { - setTuningMode(''); - } - }, [fm1Healthy, fm1NavDiscrete.value, fm1NavDiscrete.ssm, fm2Healthy, fm2NavDiscrete.value, fm2NavDiscrete.ssm]); - - return ( - {tuningMode} - ); -}; - -const VorInfo: React.FC<{index: 1 | 2, trueRef: boolean, mode: EfisNdMode }> = ({ index, trueRef, mode }) => { - const [vorIdent] = useSimVar(`NAV IDENT:${index}`, 'string'); - const [vorFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index}`, 'megahertz'); - const [vorHasDme] = useSimVar(`NAV HAS DME:${index}`, 'bool'); - const [dmeDistance] = useSimVar(`NAV DME:${index}`, 'nautical miles'); - const [vorAvailable] = useSimVar(`NAV HAS NAV:${index}`, 'boolean'); - // FIXME should be database magvar, not just when received - const [stationDeclination] = useSimVar(`NAV MAGVAR:${index}`, 'degrees'); - const [stationLocation] = useSimVar(`NAV VOR LATLONALT:${index}`, 'latlonalt'); - const [stationRefTrue, setStationRefTrue] = useState(false); - const [corrected, setCorrected] = useState(false); - const [magWarning, setMagWarning] = useState(false); - const [trueWarning, setTrueWarning] = useState(false); - - useEffect(() => { - setStationRefTrue(stationLocation.lat > 75 && stationDeclination < Number.EPSILON); - }, [stationDeclination, stationLocation.lat]); - - useEffect(() => { - setCorrected(vorAvailable && !!(trueRef) !== stationRefTrue && mode !== EfisNdMode.ROSE_VOR && mode !== EfisNdMode.ROSE_ILS); - setMagWarning(vorAvailable && !!(trueRef) && !stationRefTrue && (mode === EfisNdMode.ROSE_VOR || mode === EfisNdMode.ROSE_ILS)); - setTrueWarning(vorAvailable && !(trueRef) && stationRefTrue && (mode === EfisNdMode.ROSE_VOR || mode === EfisNdMode.ROSE_ILS)); - }, [trueRef, stationRefTrue, mode, vorAvailable]); - - const x = index === 1 ? 37 : 668; - - const bigLittle = (value: number, digits: number) => { - const [intPart, decimalPart] = value.toFixed(digits).split('.', 2); - return ( - <> - {intPart} - - . - {decimalPart} - - - ); - }; - - const freqText = bigLittle(vorFrequency, 2); - let dmeText = <>---; - if (vorHasDme && dmeDistance > 0) { - if (dmeDistance > 20) { - dmeText = <>{dmeDistance.toFixed(0)}; - } else { - dmeText = bigLittle(dmeDistance, 1); - } - } - - const path = index === 1 ? 'M25,675 L25,680 L37,696 L13,696 L25,680 M25,696 L25,719' : 'M749,719 L749,696 L755,696 L743,680 L731,696 L737,696 L737,719 M743,680 L743,675'; - - return ( - - - - VOR - {index} - - {(vorAvailable || vorHasDme) && vorFrequency > 1 && ( - <> - {vorIdent} - CORR - MAG - TRUE - - )} - {!(vorAvailable || vorHasDme) && vorFrequency > 1 && ( - {freqText} - )} - - 20 ? x + 46 : x + 58} y={759} fontSize={24} fill="#00ff00" textAnchor="end">{dmeText} - NM - - - - ); -}; - -const AdfInfo: React.FC<{index: 1 | 2}> = ({ index }) => { - const [adfIdent] = useSimVar(`ADF IDENT:${index}`, 'string'); - const [adfFrequency] = useSimVar(`ADF ACTIVE FREQUENCY:${index}`, 'kilohertz'); - const [adfAvailable] = useSimVar(`ADF SIGNAL:${index}`, 'boolean'); - - const x = index === 1 ? 37 : 668; - - const path = index === 1 ? 'M31,686 L25,680 L19,686 M25,680 L25,719' : 'M749,719 L749,696 L743,690 L737,696 L737,719 M743,690 L743,675'; - - return ( - - - - ADF - {index} - - {adfAvailable && ( - {adfIdent} - )} - {!adfAvailable && adfFrequency > 0 && ( - {Math.floor(adfFrequency).toFixed(0)} - )} - - - ); -}; - -export const RadioNavInfo: React.FC = ({ index, side, trueRef, mode }) => { - const [navaidMode] = useSimVar(`L:A32NX_EFIS_${side}_NAVAID_${index}_MODE`, 'enum'); - - if (navaidMode === NavAidMode.VOR) { - return ; - } - if (navaidMode === NavAidMode.ADF) { - return ; - } - return <>; -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNeedles.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNeedles.tsx deleted file mode 100644 index 00b72564ede..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/RadioNeedles.tsx +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { useEffect, useState } from 'react'; -import { useSimVar } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, EfisSide, NavAidMode } from '@shared/NavigationDisplay'; - -type RadioNavPointerProps = { index: 1 | 2, side: EfisSide, displayMode: EfisNdMode, centreHeight: number, trueRef: boolean }; - -const AdfNeedle: React.FC> = ({ index, displayMode, centreHeight }) => { - const [relativeBearing] = useSimVar(`ADF RADIAL:${index}`, 'degrees'); - const [available] = useSimVar(`ADF SIGNAL:${index}`, 'number'); - - let paths: Array; - - switch (displayMode) { - case EfisNdMode.ARC: - paths = [ - 'M384,251 L384,128 M370,179 L384,155 L398,179 M384,1112 L384,989 M370,1085 L384,1061 L398,1085', - 'M370,251 L370,219 L384,195 L398,219 L398,251 M384,195 L384,128 M384,1112 L384,1023 M370,989 L370,1040 L384,1023 L398,1040 L398,989', - ]; - break; - case EfisNdMode.ROSE_ILS: - case EfisNdMode.ROSE_VOR: - case EfisNdMode.ROSE_NAV: - paths = [ - 'M384,257 L384,134 M370,185 L384,161 L398,185 M384,634 L384,511 M370,607 L384,583 L398,607', - 'M370,257 L370,225 L384,201 L398,225 L398,257 M384,201 L384,134 M384,634 L384,545 M370,511 L370,562 L384,545 L398,562 L398,511', - ]; - break; - default: - console.error(`RadioNeedle: invalid display mode: ${displayMode}`); - return null; - } - - return available && ( - - - - - ); -}; - -const VorNeedle: React.FC> = ({ index, displayMode, centreHeight, trueRef }) => { - const [relativeBearing] = useSimVar(`NAV RELATIVE BEARING TO STATION:${index}`, 'degrees'); - const [available] = useSimVar(`NAV HAS NAV:${index}`, 'number'); - const [isLoc] = useSimVar(`NAV HAS LOCALIZER:${index}`, 'number'); - const [stationDeclination] = useSimVar(`NAV MAGVAR:${index}`, 'degrees'); - const [stationLocation] = useSimVar(`NAV VOR LATLONALT:${index}`, 'latlonalt'); - const [stationRefTrue, setStationRefTrue] = useState(false); - - useEffect(() => { - setStationRefTrue(stationLocation.lat > 75 && stationDeclination < Number.EPSILON); - }, [stationDeclination, stationLocation.lat]); - - let paths: Array; - - switch (displayMode) { - case EfisNdMode.ARC: - paths = [ - 'M384,251 L384,179 M384,128 L384,155 L370,179 L398,179 L384,155 M384,1112 L384,1085 M384,989 L384,1061 L370,1085 L398,1085 L384,1061', - 'M377,251 L377,219 L370,219 L384,195 L398,219 L391,219 L391,251 M384,195 L384,128 M384,1112 L384,1045 M377,989 L377,1045 L391,1045 L391,989', - ]; - break; - case EfisNdMode.ROSE_ILS: - case EfisNdMode.ROSE_VOR: - case EfisNdMode.ROSE_NAV: - paths = [ - 'M384,257 L384,185 M384,134 L384,161 L370,185 L398,185 L384,161 M384,634 L384,607 M384,511 L384,583 L370,607 L398,607 L384,583', - 'M377,257 L377,225 L370,225 L384,201 L398,225 L391,225 L391,256 M384,201 L384,134 M384,634 L384,567 M377,511 L377,567 L391,567 L391,511', - ]; - break; - default: - console.error(`RadioNeedle: invalid display mode: ${displayMode}`); - return null; - } - - // FIXME pointers should never be correct in ROSE VOR/LS... easier when VOR/MKR LRU is implemented - - return available && !isLoc && ( - - - - - ); -}; - -export const RadioNeedle: React.FC = ({ index, side, displayMode, centreHeight, trueRef }) => { - const [mode] = useSimVar(`L:A32NX_EFIS_${side}_NAVAID_${index}_MODE`, 'enum'); - - switch (mode) { - case NavAidMode.ADF: - return ; - case NavAidMode.VOR: - return ; - case NavAidMode.Off: - default: - return null; - } -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/SpeedIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/SpeedIndicator.tsx deleted file mode 100644 index 93328723280..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/SpeedIndicator.tsx +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC } from 'react'; -import { Layer, Arinc429Word, useArinc429Var } from '@flybywiresim/fbw-sdk'; -import { AdirsTasDrivenIndicatorProps } from '../index'; - -export const SpeedIndicator: FC = ({ adrs, irs }) => { - const tas: Arinc429Word = useArinc429Var(`L:A32NX_ADIRS_ADR_${adrs}_TRUE_AIRSPEED`, 200); - const gs: Arinc429Word = useArinc429Var(`L:A32NX_ADIRS_IR_${irs}_GROUND_SPEED`, 200); - - let tasText: string; - if (!tas.isNormalOperation()) { - tasText = ''; - } else if (tas.value < 0.00001) { - tasText = '---'; - } else { - tasText = Math.round(tas.value).toString().padStart(3, '0'); - } - - return ( - - GS - - {gs.isNormalOperation() ? Math.round(gs.value).toString().padStart(3) : '' } - - TAS - - {tasText} - - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TerrainMapThresholds.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TerrainMapThresholds.tsx deleted file mode 100644 index 3ba57b5cd16..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TerrainMapThresholds.tsx +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React from 'react'; -import { EfisSide } from '@shared/NavigationDisplay'; -import { useSimVar } from '@flybywiresim/fbw-sdk'; - -enum TerrainLevelMode { - PeaksMode = 0, - Warning = 1, - Caution = 2, -} - -export interface TerrainMapThresholdsProps { - side: EfisSide, -} - -export const TerrainMapThresholds: React.FC = ({ side }) => { - const [minElevation] = useSimVar(`L:A32NX_EGPWC_ND_${side}_TERRAIN_MIN_ELEVATION`, 'number', 200); - const [minElevationMode] = useSimVar(`L:A32NX_EGPWC_ND_${side}_TERRAIN_MIN_ELEVATION_MODE`, 'number', 200); - const [maxElevation] = useSimVar(`L:A32NX_EGPWC_ND_${side}_TERRAIN_MAX_ELEVATION`, 'number', 200); - const [maxElevationMode] = useSimVar(`L:A32NX_EGPWC_ND_${side}_TERRAIN_MAX_ELEVATION_MODE`, 'number', 200); - - // terrain map is disabled - if (minElevation < 0 && maxElevation < 0) return <>; - - let lowerBorderColor = ''; - let upperBorderColor = ''; - let lowerBorder = ''; - let upperBorder = ''; - - // calculate the lower border values - if (minElevation >= 0) { - lowerBorder = String(Math.floor(minElevation / 100)).padStart(3, '0'); - } - switch (minElevationMode as TerrainLevelMode) { - case TerrainLevelMode.Caution: - lowerBorderColor = 'rgb(255, 0, 0)'; - break; - case TerrainLevelMode.Warning: - lowerBorderColor = 'rgb(255, 255, 0)'; - break; - default: - lowerBorderColor = 'rgb(0, 255, 0)'; - break; - } - - // calculate the upper border values - if (maxElevation !== 0) { - upperBorder = String(Math.round(maxElevation / 100 + 0.5)).padStart(3, '0'); - } else { - upperBorder = '000'; - } - switch (maxElevationMode as TerrainLevelMode) { - case TerrainLevelMode.Caution: - upperBorderColor = 'rgb(255, 0, 0)'; - break; - case TerrainLevelMode.Warning: - upperBorderColor = 'rgb(255, 255, 0)'; - break; - default: - upperBorderColor = 'rgb(0, 255, 0)'; - break; - } - - return ( - <> - - TERR - - - {upperBorder} - - - - {lowerBorder} - - - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/ToWaypointIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/ToWaypointIndicator.tsx deleted file mode 100644 index 317fc965634..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/ToWaypointIndicator.tsx +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, memo, useEffect, useState } from 'react'; -import { Layer, useSimVar, SimVarString } from '@flybywiresim/fbw-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; - -export type ToWaypointIndicatorProps = { - side: EfisSide, - trueRef: boolean, -} - -export const ToWaypointIndicator: FC = memo(({ side, trueRef }) => { - // TODO replace with appropriate ARINC 429 labels - - const [ident, setIdent] = useState(null); - const [ident0] = useSimVar(`L:A32NX_EFIS_${side}_TO_WPT_IDENT_0`, 'number', 500); - const [ident1] = useSimVar(`L:A32NX_EFIS_${side}_TO_WPT_IDENT_1`, 'number', 500); - const [bearing] = useSimVar(`L:A32NX_EFIS_${side}_TO_WPT_BEARING`, 'Degrees'); - const [trueBearing] = useSimVar(`L:A32NX_EFIS_${side}_TO_WPT_TRUE_BEARING`, 'Degrees'); - const [distance] = useSimVar(`L:A32NX_EFIS_${side}_TO_WPT_DISTANCE`, 'Number'); - const [eta] = useSimVar(`L:A32NX_EFIS_${side}_TO_WPT_ETA`, 'Seconds'); - - useEffect(() => { - // EIS2 can only display 9 characters for the ident - setIdent(SimVarString.unpack([ident0, ident1])); - }, [ident0, ident1]); - - let distanceFixed; - let distanceIntegralPart; - let distanceDecimalPart; - - /* - * distance < 20nm: XX.Y NM - * distance > 20nm: XXXX NM - */ - if (!distance) { - distanceFixed = ''; - distanceIntegralPart = ''; - distanceDecimalPart = ''; - } else if (distance < 20) { - distanceFixed = distance.toFixed(1); - [distanceIntegralPart, distanceDecimalPart] = distanceFixed.split('.'); - } else { - distanceFixed = Math.round(Math.min(9999, distance)); - } - - const hh = Math.floor(eta / 3600); - const mm = Math.floor((eta % 3600) / 60); - - const utc = `${hh.toString().padStart(2, '0')}:${mm.toString().padStart(2, '0')}`; - - return ( - - {ident && ( - {ident} - )} - - {bearing && bearing !== -1 && Number.isFinite(bearing) && ( - <> - {(Math.round(trueRef ? trueBearing : bearing)).toString().padStart(3, '0')} - {trueRef ? 'T' : '°'} - - )} - - {distance && distance !== -1 && Number.isFinite(distance) && ( - <> - {distance < 20 ? ( - <> - {distanceIntegralPart} - . - {distanceDecimalPart} - - ) : ( - <> - {distanceFixed} - - )} - - NM - - )} - - {eta !== -1 && utc && ( - {utc} - )} - - ); -}); diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TopMessages.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TopMessages.tsx deleted file mode 100644 index 0ef1e560bdc..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TopMessages.tsx +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { useEffect, useState } from 'react'; -import { Layer, Arinc429Word, SimVarString, useSimVar } from '@flybywiresim/fbw-sdk'; -import { EfisSide } from '@shared/NavigationDisplay'; - -type TopMessagesProps = { - side: EfisSide, - ppos: LatLongData, - trueTrack: Arinc429Word, - trueRef: boolean, -} - -type GridTrackProps = { - gridTrack: number, -}; - -const GridTrack: React.FC = ({ gridTrack }) => ( - <> - - - - â—‡ - {gridTrack?.toFixed(0).padStart(3, '0') ?? ''} - - - ° - G - - - -); - -type TrueFlagProps = { - xOffset?: number, - box: boolean, -}; - -const TrueFlag: React.FC = ({ xOffset = 0, box }) => ( - <> - - TRUE - -); - -export const TopMessages: React.FC = ({ side, ppos, trueTrack, trueRef }) => { - const [apprMsg0] = useSimVar(`L:A32NX_EFIS_${side}_APPR_MSG_0`, 'number', 5000); - const [apprMsg1] = useSimVar(`L:A32NX_EFIS_${side}_APPR_MSG_1`, 'number', 5000); - const [apprMsg, setApprMsg] = useState(null); - - const [gridTrack, setGridTrack] = useState(null); - useEffect(() => { - if (trueTrack.isNormalOperation() && Math.abs(ppos.lat) > 65) { - setGridTrack(Math.round(Avionics.Utils.clampAngle(trueTrack.value - Math.sign(ppos.lat) * ppos.long)) % 360); - } else { - setGridTrack(null); - } - }, [ppos.lat.toFixed(0), ppos.long.toFixed(1), trueTrack.value.toFixed(0), trueTrack.ssm]); - - useEffect(() => { - const msg = SimVarString.unpack([apprMsg0, apprMsg1]); - setApprMsg(msg.length > 0 ? msg : null); - }, [apprMsg0, apprMsg1]); - - return ( - <> - - {apprMsg ?? ''} - - - - - - - - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TrackLine.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TrackLine.tsx deleted file mode 100644 index a7ca4acb7b4..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/TrackLine.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import { MathUtils } from '@flybywiresim/fbw-sdk'; -import { NdSymbol } from '@shared/NavigationDisplay'; -import React, { memo, useEffect, useState } from 'react'; -import { SymbolMarker } from './FlightPlan'; -import { MapParameters } from '../utils/MapParameters'; - -interface TrackLineProps { - x: number, - y: number, - heading: number, - track: number, - groundSpeed: Knots, - mapParams: MapParameters, - symbols: NdSymbol[], - ndRange: number, -} - -export const TrackLine: React.FC = memo(({ x, y, heading, track, mapParams, groundSpeed, symbols, ndRange }) => { - const rotate = MathUtils.diffAngle(heading, track); - const [lastUpdateTime, setLastUpdateTime] = useState(Date.now()); - - useEffect(() => { - setLastUpdateTime(Date.now()); - }, [symbols]); - - return ( - - - - - {symbols.map((symbol) => { - // We only want to place the symbol on the track line if it does not have a location on the flight plan. - if (!symbol.distanceFromAirplane || symbol.location) { - return false; - } - - const dy = (symbol.distanceFromAirplane - groundSpeed * (Date.now() - lastUpdateTime) / 1000 / 60 / 60) * mapParams.nmToPx; - return ; - })} - - ); -}); diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Traffic.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Traffic.tsx deleted file mode 100644 index 775f02a45f7..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/Traffic.tsx +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -/* eslint-disable camelcase */ -import { useSimVar, useFlowSyncEvent, MathUtils, Layer, usePersistentProperty } from '@flybywiresim/fbw-sdk'; -import React, { FC, useState, memo, useEffect } from 'react'; -import { TCAS_CONST as TCAS, TaRaIntrusion, TaRaIndex } from '@tcas/lib/TcasConstants'; -import { Coordinates } from '@fmgc/flightplanning/data/geo'; -import { EfisNdMode, NdTraffic } from '@shared/NavigationDisplay'; -import { MapParameters } from '../utils/MapParameters'; - -export type TcasProps = { - mapParams: MapParameters, - mode: EfisNdMode.ARC | EfisNdMode.ROSE_NAV | EfisNdMode.ROSE_ILS | EfisNdMode.ROSE_VOR, -} - -type TcasMask = [number, number][]; - -const TCAS_MASK_ARC: TcasMask = [ - // ARC - [-384, -310], [-384, 0], [-264, 0], [-210, 59], [-210, 143], - [210, 143], [210, 0], [267, -61], [384, -61], - [384, -310], [340, -355], [300, -390], [240, -431.5], - [180, -460], [100, -482], [0, -492], [-100, -482], - [-180, -460], [-240, -431.5], [-300, -390], [-340, -355], - [-384, -310], -]; - -const TCAS_MASK_ROSE: TcasMask = [ - // ROSE NAV - [-340, -227], [-103, -227], [-50, -244], - [0, -250], [50, -244], [103, -227], [340, -227], - [340, 180], [267, 180], [210, 241], [210, 383], - [-210, 383], [-210, 300], [-264, 241], [-340, 241], [-340, -227], -]; - -const useAirTraffic = (mapParams, mode) : NdTraffic[] => { - const [airTraffic, setAirTraffic] = useState([]); - const tcasMask = (mode === EfisNdMode.ARC ? TCAS_MASK_ARC : TCAS_MASK_ROSE); - useFlowSyncEvent('A32NX_TCAS_TRAFFIC', (_topic, data) => { - if (data) { - setAirTraffic(trafficToDisplay(data, mapParams, tcasMask)); - } - }); - useEffect(() => { - setAirTraffic(trafficToDisplay(airTraffic, mapParams, tcasMask)); - }, [mapParams?.nmRadius, mode]); - return airTraffic; -}; - -const trafficToDisplay = (airTraffic, mapParams, tcasMask) => ( - airTraffic.map((traffic: NdTraffic) => { - const latLong: Coordinates = { lat: traffic.lat, long: traffic.lon }; - let [x, y] = mapParams.coordinatesToXYy(latLong); - - // TODO FIXME: Full time option installed: For all ranges except in ZOOM ranges, NDRange > 9NM - if (!MathUtils.pointInPolygon(x, y, tcasMask)) { - if (traffic.intrusionLevel < TaRaIntrusion.TA) { - traffic.alive = false; - return traffic; - } - const ret: [number, number] | null = MathUtils.intersectWithPolygon(x, y, 0, 0, tcasMask); - if (ret) [x, y] = ret; - } - traffic.alive = true; - traffic.posX = x; - traffic.posY = y; - return traffic; - }) -); - -export const Traffic: FC = ({ mapParams, mode }) => { - const airTraffic = useAirTraffic(mapParams, mode); - const [debug] = usePersistentProperty('TCAS_DEBUG', '0'); - const [sensitivity] = useSimVar('L:A32NX_TCAS_SENSITIVITY', 'number', 200); - const x: number = 361.5; - const y: number = (mode === EfisNdMode.ARC) ? 606.5 : 368; - - if (debug !== '0') { - const dmodRa: number = mapParams.nmToPx * (TCAS.DMOD[sensitivity || 1][TaRaIndex.RA]); - const dmodTa: number = mapParams.nmToPx * (TCAS.DMOD[sensitivity || 1][TaRaIndex.TA]); - return ( - - {dmodTa >= 0 - && ( - - )} - {dmodRa >= 0 - && ( - - )} - - - {`SENSITIVITY: ${sensitivity}`} - - - {'DMOD: '} - - - {dmodTa.toFixed(3)} - - - {' | '} - - - {dmodRa.toFixed(3)} - - - {'TAU THR: '} - - - {TCAS.TAU[sensitivity || 1][TaRaIndex.TA]} - - - {' | '} - - - {TCAS.TAU[sensitivity || 1][TaRaIndex.RA]} - - - - {'Z THR: '} - - - {TCAS.ZTHR[sensitivity || 1][TaRaIndex.TA]} - - - {' | '} - - - {TCAS.ZTHR[sensitivity || 1][TaRaIndex.RA]} - - - - {'ALIM: '} - - - {TCAS.ALIM[sensitivity]} - - - {airTraffic.map((tf) => ( - tf.alive ? ( - - ); - } - return ( - - {airTraffic.map((tf) => ( - tf.alive ? ( - - ) : null - ))} - - - ); -}; - -type TrafficProp = { - x: number | undefined, - y: number | undefined, - relativeAlt: number | undefined, - vertSpeed: number | undefined, - intrusionLevel: TaRaIntrusion | undefined, -} - -const TrafficIndicator: FC = memo(({ x, y, relativeAlt, vertSpeed, intrusionLevel }) => { - if (relativeAlt === undefined || vertSpeed === undefined || x === undefined || y === undefined) return <>; - let color = '#ffffff'; - switch (intrusionLevel) { - case TaRaIntrusion.TA: - color = '#e38c56'; - break; - case TaRaIntrusion.RA: - color = '#ff0000'; - break; - default: - break; - } - - // Place relative altitude above/below - const relAltY: number = (relativeAlt > 0) ? 7 : 43.5; - - return ( - <> - - {intrusionLevel === TaRaIntrusion.TRAFFIC && } - {intrusionLevel === TaRaIntrusion.PROXIMITY && } - {intrusionLevel === TaRaIntrusion.TA && } - {intrusionLevel === TaRaIntrusion.RA && } - - - - {`${relativeAlt > 0 ? '+' : '-'}${Math.abs(relativeAlt) < 10 ? '0' : ''}${Math.abs(relativeAlt)}`} - - - {(vertSpeed <= -500) && ( - <> - - - - - - )} - {(vertSpeed >= 500) && ( - <> - - - - - - )} - - - - ); -}); - -type TrafficPropDebug = { - x: number | undefined, - y: number | undefined, - relativeAlt: number | undefined, - vertSpeed: number | undefined, - intrusionLevel: TaRaIntrusion | undefined, - ID: string, - hidden: boolean | undefined, - seen: number | undefined, - raTau: string | undefined, - taTau: string | undefined, - vTau: string | undefined, - closureRate: string | undefined, - closureAccel: string | undefined -} - -const TrafficIndicatorDebug: FC = memo(({ x, y, relativeAlt, vertSpeed, intrusionLevel, ID, hidden, seen, raTau, taTau, vTau, closureRate, closureAccel }) => { - if (relativeAlt === undefined || vertSpeed === undefined || x === undefined || y === undefined) return <>; - let color = '#ffffff'; - switch (intrusionLevel) { - case TaRaIntrusion.TA: - color = '#e38c56'; - break; - case TaRaIntrusion.RA: - color = '#ff0000'; - break; - default: - break; - } - - // Place relative altitude above/below - const relAltY: number = (relativeAlt > 0) ? 7 : 43.5; - const debugY1: number = (relativeAlt > 0) ? 38 : -1; - const debugY2: number = (relativeAlt > 0) ? 50 : -13; - - return ( - <> - - {intrusionLevel === TaRaIntrusion.TRAFFIC && } - { - intrusionLevel === TaRaIntrusion.PROXIMITY - && - } - {intrusionLevel === TaRaIntrusion.TA && } - {intrusionLevel === TaRaIntrusion.RA && } - - - - {`${relativeAlt > 0 ? '+' : '-'}${Math.abs(relativeAlt) < 10 ? '0' : ''}${Math.abs(relativeAlt)}`} - - {!hidden && ( - <> - - {`${ID} [${closureRate}|${closureAccel}] <${seen}>`} - - - {`R ${raTau || '-'} V ${vTau || '-'} T ${taTau || '-'}`} - - - )} - - {(vertSpeed <= -500) && ( - <> - - - - - - )} - {(vertSpeed >= 500) && ( - <> - - - - - - )} - - - - ); -}); diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/WindIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/WindIndicator.tsx deleted file mode 100644 index 05680a4c81f..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/WindIndicator.tsx +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC } from 'react'; -import { Layer, useArinc429Var, Arinc429Word } from '@flybywiresim/fbw-sdk'; -import { AdirsTasDrivenIndicatorProps } from '../index'; - -const mod = (x: number, n: number) => x - Math.floor(x / n) * n; - -export const WindIndicator: FC = ({ irs }) => { - const windDirection: Arinc429Word = useArinc429Var(`L:A32NX_ADIRS_IR_${irs}_WIND_DIRECTION_BNR`, 500); - const windSpeed: Arinc429Word = useArinc429Var(`L:A32NX_ADIRS_IR_${irs}_WIND_SPEED_BNR`, 500); - const planeHeading: Arinc429Word = useArinc429Var(`L:A32NX_ADIRS_IR_${irs}_TRUE_HEADING`, 500); - - const windDirection360 = windDirection.value < 0 ? windDirection.value + 360 : windDirection.value; - - let windDirectionText: string; - let windSpeedText: string; - let windArrowShow: boolean = false; - if (windSpeed.isFailureWarning() || windDirection.isFailureWarning()) { - windDirectionText = ''; - windSpeedText = ''; - windArrowShow = false; - } else if (windSpeed.isNoComputedData() || windDirection.isNoComputedData()) { - windDirectionText = '---'; - windSpeedText = '---'; - } else { - windDirectionText = Math.round(windDirection360).toString().padStart(3, '0'); - windSpeedText = Math.round(windSpeed.value).toString(); - if (windSpeed.value >= 2) { - windArrowShow = true; - } - } - - let rotation; - if (planeHeading.isNormalOperation() && windDirection.isNormalOperation()) { - rotation = mod(Math.round(windDirection360) - Math.round(planeHeading.value) + 180, 360); - } - return ( - - - {windDirectionText} - - / - - {windSpeedText} - - {windArrowShow && ( - - )} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/FMMessages.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/FMMessages.tsx deleted file mode 100644 index 00f446b21c9..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/FMMessages.tsx +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, useEffect, useState } from 'react'; -import { Layer, useSimVar } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode } from '@shared/NavigationDisplay'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; - -export const FMMessages: FC<{ modeIndex: EfisNdMode, side: 'L' | 'R' }> = ({ modeIndex, side }) => { - const [activeMessages, setActiveMessages] = useState([]); - - // TODO check FM failure and get messages from other FM - const [messageFlags] = useSimVar(`L:A32NX_EFIS_${side}_ND_FM_MESSAGE_FLAGS`, 'number', 500); - - useEffect(() => { - const newActiveMessages = activeMessages.slice(); - // the list must be ordered by priority, and LIFO for equal priority - for (const message of Object.values(FMMessageTypes)) { - if (((message.ndFlag ?? 0) & messageFlags) > 0) { - if (newActiveMessages.findIndex(({ ndFlag }) => ndFlag === message.ndFlag) === -1) { - newActiveMessages.push(message); - newActiveMessages.sort((a, b) => (b.ndPriority ?? 0) - (a.ndPriority ?? 0)); - } - } else if ((message.ndFlag ?? 0) > 0) { - const idx = newActiveMessages.findIndex(({ ndFlag }) => ndFlag === message.ndFlag); - if (idx !== -1) { - newActiveMessages.splice(idx, 1); - } - } - } - setActiveMessages(newActiveMessages); - }, [messageFlags]); - - if (modeIndex !== EfisNdMode.ARC && modeIndex !== EfisNdMode.PLAN && modeIndex !== EfisNdMode.ROSE_NAV || activeMessages.length < 1) { - return null; - } - - return ( - - - - { /* the text message is offset from centre on the real one... - guess by the width of the multiple message arrow... */ } - - {`${activeMessages[activeMessages.length - 1].text ?? activeMessages[activeMessages.length - 1].efisText}`} - - - { activeMessages.length > 1 && ( - - )} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/NavigationDisplayMessages.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/NavigationDisplayMessages.tsx deleted file mode 100644 index de1665dae69..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/NavigationDisplayMessages.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import { useSimVar } from '@flybywiresim/fbw-sdk'; -import React, { FC } from 'react'; -import { EfisNdMode } from '@shared/NavigationDisplay'; - -export interface NavigationDisplayMessagesProps { - adirsAlign: boolean, - mode: EfisNdMode, - modeChangeShown: boolean, - rangeChangeShown: boolean, -} - -export const NavigationDisplayMessages: FC = ({ adirsAlign, mode, modeChangeShown, rangeChangeShown }) => { - // Do not show general messages in ROSE VOR/ILS or ANF (latter is not in neo) - const modeValidForGeneralMessages = (mode !== EfisNdMode.ROSE_VOR && mode !== EfisNdMode.ROSE_ILS) && (adirsAlign || mode === EfisNdMode.PLAN); - - const [tcasState] = useSimVar('L:A32NX_TCAS_STATE', 'Enum', 200); - - return ( - <> - - MODE CHANGE - - - RANGE CHANGE - - { tcasState === 2 && (mode === EfisNdMode.PLAN || mode === EfisNdMode.ROSE_ILS || mode === EfisNdMode.ROSE_VOR) && !modeChangeShown && !rangeChangeShown - && ( - - TCAS: CHANGE MODE - - )} - { tcasState === 3 && (mode === EfisNdMode.PLAN || mode === EfisNdMode.ROSE_ILS || mode === EfisNdMode.ROSE_VOR) && !modeChangeShown && !rangeChangeShown - && ( - - TCAS: CHANGE MODE - - )} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/TcasWxrMessages.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/TcasWxrMessages.tsx deleted file mode 100644 index ad7d2da3f7d..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/elements/messages/TcasWxrMessages.tsx +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC } from 'react'; -import { Layer, useSimVar } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, TcasWxrMessage } from '@shared/NavigationDisplay'; - -/* -Messages in priority order, from 1-12 (full set with ATSAW and nice weather radar) -[ TCAS (amber) | WEATHER AHEAD (amber) ] -[ TCAS (amber) | ADS-B (amber) ] -[ TCAS (amber) | ADS-B ONLY (white) ] -[ TCAS (amber) | ] -[ XX.YNM+NN^ | XX.YNM+NN^ ] -[ XX.YNM+NN^ | ADS-B (amber) ] -[ XX.YNM+NN^ | ] -[ TA ONLY (white) | WEATHER AHEAD (amber) ] -[ TA ONLY (white) | ADS-B (amber) ] -[ TA ONLY (white) | ] -[ | ADS-B (amber) ] -*/ - -export const TcasWxrMessages: FC<{ modeIndex: EfisNdMode}> = ({ modeIndex }) => { - // TODO get data and decide what to display - - let leftMessage: TcasWxrMessage | undefined; - let rightMessage: TcasWxrMessage | undefined; - - const [tcasOnly] = useSimVar('L:A32NX_TCAS_TA_ONLY', 'boolean', 200); - const [tcasFault] = useSimVar('L:A32NX_TCAS_FAULT', 'boolean', 200); - - if (tcasFault) { - leftMessage = { text: 'TCAS', color: 'Amber' }; - } else if (tcasOnly) { - leftMessage = { text: 'TA ONLY', color: 'White' }; - } - - if (modeIndex !== EfisNdMode.ARC && modeIndex !== EfisNdMode.ROSE_NAV && modeIndex !== EfisNdMode.ROSE_VOR && modeIndex !== EfisNdMode.ROSE_ILS || (!leftMessage && !rightMessage)) { - return null; - } - - const y = (modeIndex === EfisNdMode.ROSE_VOR || modeIndex === EfisNdMode.ROSE_ILS) ? 713 : 684; - - return ( - - { /* we fill/mask the map under both message boxes, per IRL refs */ } - { (modeIndex === EfisNdMode.ARC || modeIndex === EfisNdMode.ROSE_NAV) && ( - - )} - - - - { (leftMessage) && ( - - {leftMessage.text} - - )} - - { (rightMessage) && ( - - {rightMessage.text} - - )} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/index.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/index.tsx deleted file mode 100644 index 0fed2ffce9a..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/index.tsx +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { useEffect, useRef, useCallback, useState } from 'react'; -import { DisplayUnit } from '@instruments/common/displayUnit'; -import { FlightPlanProvider } from '@instruments/common/flightplan'; -import { useSimVar, useArinc429Var, useFlowSyncEvent, getSupplier } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, NdSymbol, rangeSettings } from '@shared/NavigationDisplay'; -import { TerrainMapThresholds } from './elements/TerrainMapThresholds'; -import { render } from '../Common'; -import { ArcMode } from './pages/ArcMode'; -import { WindIndicator } from './elements/WindIndicator'; -import { SpeedIndicator } from './elements/SpeedIndicator'; -import { RadioNavInfo } from './elements/RadioNavInfo'; -import { Chrono } from './elements/Chrono'; -import { NavigationDisplayMessages } from './elements/messages/NavigationDisplayMessages'; -import { FMMessages } from './elements/messages/FMMessages'; -import { TcasWxrMessages } from './elements/messages/TcasWxrMessages'; -import { PlanMode } from './pages/PlanMode'; -import { RoseMode } from './pages/RoseMode'; -import './styles.scss'; -import { LnavStatus } from './elements/LnavStatus'; - -const NavigationDisplay: React.FC = () => { - const [displayIndex] = useState(() => { - const url = document.getElementsByTagName('a32nx-nd')[0].getAttribute('url'); - - return parseInt(url?.substring(url.length - 1) ?? '1', 10); - }); - const side = displayIndex === 1 ? 'L' : 'R'; - const [airDataSwitch] = useSimVar('L:A32NX_AIR_DATA_SWITCHING_KNOB', 'enum', 200); - const [attHdgSwitch] = useSimVar('L:A32NX_ATT_HDG_SWITCHING_KNOB', 'enum', 200); - const [airDataReferenceSource, setAirDataSource] = useState(displayIndex); - const [inertialReferenceSource, setInertialSource] = useState(displayIndex); - - useEffect(() => { - setAirDataSource(getSupplier(displayIndex, airDataSwitch)); - }, [airDataSwitch]); - - useEffect(() => { - setInertialSource(getSupplier(displayIndex, attHdgSwitch)); - }, [attHdgSwitch]); - - const arincLat = useArinc429Var(`L:A32NX_ADIRS_IR_${inertialReferenceSource}_LATITUDE`, 200); - const arincLong = useArinc429Var(`L:A32NX_ADIRS_IR_${inertialReferenceSource}_LONGITUDE`, 200); - const adirsAlign = arincLat.isNormalOperation() && arincLong.isNormalOperation(); - - const ppos = (adirsAlign) ? { lat: arincLat.value, long: arincLong.value } : { lat: NaN, long: NaN }; - - const [rangeIndex] = useSimVar(displayIndex === 1 ? 'L:A32NX_EFIS_L_ND_RANGE' : 'L:A32NX_EFIS_R_ND_RANGE', 'number', 100); - const [modeIndex] = useSimVar(displayIndex === 1 ? 'L:A32NX_EFIS_L_ND_MODE' : 'L:A32NX_EFIS_R_ND_MODE', 'number', 100); - - const [modeChangeShown, setModeChangeShown] = useState(false); - const [rangeChangeShown, setRangeChangeShown] = useState(false); - - const firstModeUpdate = useRef(true); - const firstRangeUpdate = useRef(true); - - useEffect(() => { - if (firstModeUpdate.current) { - firstModeUpdate.current = false; - return () => {}; - } - - setModeChangeShown(true); - - const timeout = setTimeout(() => { - setModeChangeShown(false); - }, 500); // TODO looks like this depends on range or number of symbols IRL - - return () => clearTimeout(timeout); - }, [modeIndex]); - - useEffect(() => { - if (firstRangeUpdate.current) { - firstRangeUpdate.current = false; - return () => {}; - } - - // RANGE CHANGE has priority over MODE CHANGE - if (modeChangeShown) { - setModeChangeShown(false); - } - setRangeChangeShown(true); - - const timeout = setTimeout(() => { - setRangeChangeShown(false); - }, 500); // TODO looks like this depends on range or number of symbols IRL - - return () => clearTimeout(timeout); - }, [rangeIndex]); - - const [symbols, setSymbols] = useState([]); - - useFlowSyncEvent(`A32NX_EFIS_${side}_SYMBOLS`, useCallback((_topic, data) => { - if (data) { - setSymbols(data); - } - }, [])); - - const irMaint = useArinc429Var('L:A32NX_ADIRS_IR_1_MAINT_WORD'); - const [trueRefPb] = useSimVar('L:A32NX_PUSH_TRUE_REF', 'bool'); - const [trueRef, setTrueRef] = useState(false); - - useEffect(() => { - setTrueRef((irMaint.getBitValueOr(15, false) || trueRefPb) && !irMaint.getBitValueOr(2, false)); - }, [irMaint.value, trueRefPb]); - - return ( - - - - {modeIndex === EfisNdMode.PLAN && ( - - )} - {modeIndex === EfisNdMode.ARC && ( - - )} - {(modeIndex === EfisNdMode.ROSE_ILS || modeIndex === EfisNdMode.ROSE_VOR || modeIndex === EfisNdMode.ROSE_NAV) - && ( - - )} - - - - - - {true && ( - - )} - - - - {(adirsAlign && modeIndex !== EfisNdMode.PLAN) && ( - <> - - - - )} - - - - - - - ); -}; - -export type AdirsTasDrivenIndicatorProps = { - adrs: number, - irs: number -} - -render(); diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/ArcMode.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/ArcMode.tsx deleted file mode 100644 index 26cca92c519..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/ArcMode.tsx +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { memo, useEffect, useState } from 'react'; -import { useSimVar, MathUtils, useArinc429Var, getSmallestAngle } from '@flybywiresim/fbw-sdk'; -import { EfisNdRangeValue, EfisNdMode, EfisSide, NdSymbol } from '@shared/NavigationDisplay'; -import { ArmedLateralMode, isArmed, LateralMode } from '@shared/autopilot'; -import { TopMessages } from '../elements/TopMessages'; -import { FlightPlan } from '../elements/FlightPlan'; -import { MapParameters } from '../utils/MapParameters'; -import { RadioNeedle } from '../elements/RadioNeedles'; -import { ToWaypointIndicator } from '../elements/ToWaypointIndicator'; -import { CrossTrack } from '../elements/CrossTrack'; -import { TrackLine } from '../elements/TrackLine'; -import { Traffic } from '../elements/Traffic'; - -export interface ArcModeProps { - symbols: NdSymbol[], - adirsAlign: boolean, - rangeSetting: EfisNdRangeValue, - side: EfisSide, - ppos: LatLongData, - mapHidden: boolean, - trueRef: boolean, -} - -export const ArcMode: React.FC = ({ symbols, adirsAlign, rangeSetting, side, ppos, mapHidden, trueRef }) => { - // TODO arinc var selector - const magHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_HEADING'); - const magTrack = useArinc429Var('L:A32NX_ADIRS_IR_1_TRACK'); - const trueHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_TRUE_HEADING'); - const trueTrack = useArinc429Var('L:A32NX_ADIRS_IR_1_TRUE_TRACK'); - const [tcasMode] = useSimVar('L:A32NX_SWITCH_TCAS_Position', 'number'); - const [selectedHeading] = useSimVar('L:A32NX_FCU_HEADING_SELECTED', 'degrees'); - const [lsCourse] = useSimVar('L:A32NX_FM_LS_COURSE', 'number'); - const [lsDisplayed] = useSimVar(`L:BTN_LS_${side === 'L' ? 1 : 2}_FILTER_ACTIVE`, 'bool'); // TODO rename simvar - const [fmaLatMode] = useSimVar('L:A32NX_FMA_LATERAL_MODE', 'enum', 200); - const [armedLateralBitmask] = useSimVar('L:A32NX_FMA_LATERAL_ARMED', 'enum', 200); - const [groundSpeed] = useSimVar('GPS GROUND SPEED', 'Meters per second', 200); - - const heading = Number(MathUtils.fastToFixed((trueRef ? trueHeading.value : magHeading.value), 2)); - const track = Number(MathUtils.fastToFixed((trueRef ? trueTrack.value : magTrack.value), 2)); - - const [mapParams] = useState(() => { - const params = new MapParameters(); - params.compute(ppos, 0, rangeSetting, 492, trueHeading.value); - - return params; - }); - - useEffect(() => { - mapParams.compute(ppos, 0, rangeSetting, 492, trueHeading.value); - }, [ppos.lat, ppos.long, trueHeading.value, rangeSetting].map((n) => MathUtils.fastToFixed(n, 6))); - - if (adirsAlign) { - return ( - <> - - - - - - { ((fmaLatMode === LateralMode.NONE - || fmaLatMode === LateralMode.HDG - || fmaLatMode === LateralMode.TRACK) - && !isArmed(armedLateralBitmask, ArmedLateralMode.NAV)) && ( - - )} - - - - - - - - - - { lsDisplayed && } - - - - - - - - ); - } - return ( - <> - - PPOS - - ); -}; - -interface OverlayProps { - heading: number, - rangeSetting: number, - tcasMode: number, -} - -const Overlay: React.FC = memo(({ heading, rangeSetting, tcasMode }) => ( - <> - - - {/* C = 384,620 */} - - - - - - - - {/* R = 369 */} - - {(rangeSetting / 4) * 3} - {(rangeSetting / 4) * 3} - - {/* R = 246 */} - - {rangeSetting / 2} - {rangeSetting / 2} - - {/* R = 123 */} - { (tcasMode === 0 || rangeSetting > 10) && ( - - )} - { (tcasMode > 0 && rangeSetting === 10) && ( - - - - - - - - )} - - {/* R = 62 */} - { (tcasMode > 0 && rangeSetting === 20) && ( - - - - - - - - )} - - -)); - -const ArcModeOverlayDefs = memo(() => ( - <> - - - - - - - - - - - - - - - - - - - - - - {/* inverted map overlays for terrain map in WASM module */} - - - - -)); - -const ArcModeOverlayHeadingRing = memo(() => ( - <> - {/* R = 492 */} - - - - - - 0 - - - - - - - - 1 - - - - - - - - 2 - - - - - - - - 3 - - - - - - - - 4 - - - - - - - - 5 - - - - - - - - 6 - - - - - - - - 7 - - - - - - - - 8 - - - - - - - - 9 - - - - - - - - 10 - - - - - - - - 11 - - - - - - - - 12 - - - - - - - - 13 - - - - - - - - 14 - - - - - - - - 15 - - - - - - - - 16 - - - - - - - - 17 - - - - - - - - 18 - - - - - - - - 19 - - - - - - - - 20 - - - - - - - - 21 - - - - - - - - 22 - - - - - - - - 23 - - - - - - - - 24 - - - - - - - - 25 - - - - - - - - 26 - - - - - - - - 27 - - - - - - - - 28 - - - - - - - - 29 - - - - - - - - 30 - - - - - - - - 31 - - - - - - - - 32 - - - - - - - - 33 - - - - - - - - 34 - - - - - - - - 35 - - - - - -)); - -type MapFailOverlayProps = { - rangeSetting: EfisNdRangeValue, -} - -const MapFailOverlay: React.FC = memo(({ rangeSetting }) => ( - <> - <> - HDG - MAP NOT AVAIL - - - - - - - - - - - - - - - - - - - {/* C = 384,620 */} - - - - {/* R = 492 */} - - - - - - {/* R = 369 */} - - {(rangeSetting / 4) * 3} - {(rangeSetting / 4) * 3} - - {/* R = 246 */} - - {rangeSetting / 2} - {rangeSetting / 2} - - {/* R = 123 */} - - - <> - - - - - - -)); - -const Plane: React.FC = memo(() => ( - - - - - - -)); - -const TrackBug: React.FC<{heading: number, track: number}> = memo(({ heading, track }) => { - const diff = getSmallestAngle(track, heading); - if (diff > 48) { - return null; - } - return ( - <> - - - - ); -}); - -const LsCourseBug: React.FC<{heading: number, lsCourse: number}> = ({ heading, lsCourse }) => { - const diff = getSmallestAngle(lsCourse, heading); - if (lsCourse < 0 || Math.abs(diff) > 48) { - return null; - } - - return ( - <> - - - - ); -}; - -const SelectedHeadingBug: React.FC<{heading: number, selected: number}> = ({ heading, selected }) => { - if (selected < 0) { - return null; - } - - const diff = getSmallestAngle(selected, heading); - if (Math.abs(diff) <= 48) { - return ( - <> - - - - ); - } - return ( - - {`${Math.round(selected).toString().padStart(3, '0')}`} - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/PlanMode.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/PlanMode.tsx deleted file mode 100644 index 941d7ffd544..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/PlanMode.tsx +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, memo, useEffect, useState } from 'react'; -import { useSimVar, useArinc429Var } from '@flybywiresim/fbw-sdk'; -import { Coordinates } from '@fmgc/flightplanning/data/geo'; -import { EfisSide, NdSymbol } from '@shared/NavigationDisplay'; -import { CrossTrack } from '../elements/CrossTrack'; -import { ToWaypointIndicator } from '../elements/ToWaypointIndicator'; -import { FlightPlan } from '../elements/FlightPlan'; -import { MapParameters } from '../utils/MapParameters'; - -export interface PlanModeProps { - side: EfisSide, - symbols: NdSymbol[], - adirsAlign: boolean, - rangeSetting: number, - ppos: LatLongData, - mapHidden: boolean, -} - -export const PlanMode: FC = ({ side, symbols, adirsAlign, rangeSetting, ppos, mapHidden }) => { - const [planCentreLat] = useSimVar('L:A32NX_SELECTED_WAYPOINT_LAT', 'Degrees'); - const [planCentreLong] = useSimVar('L:A32NX_SELECTED_WAYPOINT_LONG', 'Degrees'); - const trueHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_TRUE_HEADING'); - const irMaint = useArinc429Var('L:A32NX_ADIRS_IR_1_MAINT_WORD'); - const [trueRefPb] = useSimVar('L:A32NX_PUSH_TRUE_REF', 'bool'); - const [trueRef, setTrueRef] = useState(false); - const [mapParams] = useState(new MapParameters()); - - useEffect(() => { - mapParams.compute({ lat: planCentreLat, long: planCentreLong }, 0, rangeSetting / 2, 250, 0); - }, [planCentreLat, planCentreLong, rangeSetting]); - - useEffect(() => { - setTrueRef((irMaint.getBitValueOr(15, false) || trueRefPb) && !irMaint.getBitValueOr(2, false)); - }, [irMaint.value, trueRefPb]); - - return ( - <> - - - - - - - {adirsAlign && !mapHidden && mapParams.valid && ( - - )} - - - - - - ); -}; - -interface OverlayProps { - rangeSetting: number, -} - -const Overlay: FC = memo(({ rangeSetting }) => ( - <> - - - - - - - - - {rangeSetting / 4} - {rangeSetting / 2} - - N - - - E - - - S - - - W - - - -)); - -interface PlaneProps { - location: Coordinates, - heading: Degrees, // True - mapParams: MapParameters, -} - -const Plane: FC = ({ location, heading, mapParams }) => { - const [x, y] = mapParams.coordinatesToXYy(location); - const rotation = mapParams.rotation(heading); - - return ( - - - - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/RoseMode.tsx b/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/RoseMode.tsx deleted file mode 100644 index b360f0d7b52..00000000000 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/pages/RoseMode.tsx +++ /dev/null @@ -1,929 +0,0 @@ -// Copyright (c) 2021-2023 FlyByWire Simulations -// -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC, memo, useEffect, useState } from 'react'; -import { useSimVar, MathUtils, useArinc429Var, Layer, getSmallestAngle } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, EfisSide, NdSymbol } from '@shared/NavigationDisplay'; -import { ArmedLateralMode, isArmed, LateralMode } from '@shared/autopilot'; -import { TopMessages } from '../elements/TopMessages'; -import { ToWaypointIndicator } from '../elements/ToWaypointIndicator'; -import { FlightPlan } from '../elements/FlightPlan'; -import { MapParameters } from '../utils/MapParameters'; -import { RadioNeedle } from '../elements/RadioNeedles'; -import { CrossTrack } from '../elements/CrossTrack'; -import { TrackLine } from '../elements/TrackLine'; -import { Traffic } from '../elements/Traffic'; - -export interface RoseModeProps { - symbols: NdSymbol[], - adirsAlign: boolean, - rangeSetting: number, - mode: EfisNdMode.ROSE_ILS | EfisNdMode.ROSE_VOR | EfisNdMode.ROSE_NAV, - side: EfisSide, - ppos: LatLongData, - mapHidden: boolean, - trueRef: boolean, -} - -export const RoseMode: FC = ({ symbols, adirsAlign, rangeSetting, mode, side, ppos, mapHidden, trueRef }) => { - const magHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_HEADING'); - const magTrack = useArinc429Var('L:A32NX_ADIRS_IR_1_TRACK'); - const trueHeading = useArinc429Var('L:A32NX_ADIRS_IR_1_TRUE_HEADING'); - const trueTrack = useArinc429Var('L:A32NX_ADIRS_IR_1_TRUE_TRACK'); - const [tcasMode] = useSimVar('L:A32NX_SWITCH_TCAS_Position', 'number'); - const [selectedHeading] = useSimVar('L:A32NX_FCU_HEADING_SELECTED', 'degrees'); - const [lsCourse] = useSimVar('L:A32NX_FM_LS_COURSE', 'number'); - const [lsDisplayed] = useSimVar(`L:BTN_LS_${side === 'L' ? 1 : 2}_FILTER_ACTIVE`, 'bool'); // TODO rename simvar - const [fmaLatMode] = useSimVar('L:A32NX_FMA_LATERAL_MODE', 'enum', 200); - const [armedLateralBitmask] = useSimVar('L:A32NX_FMA_LATERAL_ARMED', 'enum', 200); - const [groundSpeed] = useSimVar('GPS GROUND SPEED', 'Meters per second', 200); - - const heading = Number(MathUtils.fastToFixed((trueRef ? trueHeading.value : magHeading.value), 2)); - const track = Number(MathUtils.fastToFixed((trueRef ? trueTrack.value : magTrack.value), 2)); - - const [mapParams] = useState(() => { - const params = new MapParameters(); - params.compute(ppos, 0, rangeSetting / 2, 250, trueHeading.value); - - return params; - }); - - useEffect(() => { - mapParams.compute(ppos, 0, rangeSetting / 2, 250, trueHeading.value); - }, [ppos.lat, ppos.long, trueHeading.value, rangeSetting].map((n) => MathUtils.fastToFixed(n, 6))); - - if (adirsAlign) { - return ( - <> - - - { mode === EfisNdMode.ROSE_NAV && ( - - - - { ((fmaLatMode === LateralMode.NONE || fmaLatMode === LateralMode.HDG || fmaLatMode === LateralMode.TRACK) - && !isArmed(armedLateralBitmask, ArmedLateralMode.NAV)) && ( - - )} - - )} - - - - - { mode === EfisNdMode.ROSE_VOR && } - - { mode === EfisNdMode.ROSE_ILS && } - - { mode === EfisNdMode.ROSE_NAV && } - { mode === EfisNdMode.ROSE_VOR && } - { mode === EfisNdMode.ROSE_ILS && } - - - - { mode === EfisNdMode.ROSE_NAV && lsDisplayed && } - - { mode === EfisNdMode.ROSE_ILS && } - - {mode === EfisNdMode.ROSE_NAV && } - - - - - ); - } - return ( - <> - - - PPOS - - ); -}; - -interface OverlayProps { - heading: number, - rangeSetting: number, - tcasMode: number, -} - -const Overlay: FC = ({ heading, rangeSetting, tcasMode }) => ( - <> - - - {/* C = 384,384 */} - - - - - - - {/* R = 125, middle range ring */} - { (tcasMode === 0 || rangeSetting > 10) - && ( - - )} - - {/* middle range ring replaced with tcas range ticks */} - { (tcasMode > 0 && rangeSetting === 10) - && ( - - - - - - - - - - - - - - - )} - - {/* R = 62, tcas range ticks */} - { (tcasMode > 0 && rangeSetting === 20) - && ( - - - - - - - - - - - - - - - )} - - {rangeSetting / 2} - {rangeSetting / 4} - - {/* fixed triangle markers every 45 deg except 12 o'clock */} - - - - - - - - - -); - -const RoseModeOverlayDefs = memo(() => ( - <> - - - - - - - - - - {/* inverted map overlays for terrain map in WASM module */} - - - - -)); - -const RoseModeOverlayHeadingRing = memo(() => ( - <> - {/* R = 250 */} - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - 6 - - - - - - - - - - - - - - - - - - - - - - - - - 9 - - - - - - - - - - - - - - - - - - - - - - - - - 12 - - - - - - - - - - - - - - - - - - - - - - - - - 15 - - - - - - - - - - - - - - - - - - - - - - - - - 18 - - - - - - - - - - - - - - - - - - - - - - - - - 21 - - - - - - - - - - - - - - - - - - - - - - - - - 24 - - - - - - - - - - - - - - - - - - - - - - - - - 27 - - - - - - - - - - - - - - - - - - - - - - - - - 30 - - - - - - - - - - - - - - - - - - - - - - - - - 33 - - - - - - - - - - - - - - - - - - - - - - -)); - -const MapFailOverlay: FC> = memo(({ rangeSetting }) => ( - <> - HDG - MAP NOT AVAIL - - - - - - {/* C = 384,384 */} - - - - {/* R = 250 */} - - - - {/* R = 125, middle range ring */} - - - {rangeSetting / 2} - {rangeSetting / 4} - -)); - -// TODO true ref -const VorCaptureOverlay: React.FC<{ - heading: number, - side: EfisSide, -}> = ({ heading, side }) => { - const index = side === 'L' ? 1 : 2; - const [course] = useSimVar(`NAV OBS:${index}`, 'degrees'); - const [vorFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index}`, 'megahertz'); - const [courseDeviation] = useSimVar(`NAV RADIAL ERROR:${index}`, 'degrees', 20); - const [available] = useSimVar(`NAV HAS NAV:${index}`, 'number'); - const [toward, setToward] = useState(true); - const [cdiPx, setCdiPx] = useState(12); - - useEffect(() => { - let cdiDegrees: number; - if (Math.abs(courseDeviation) <= 90) { - cdiDegrees = courseDeviation; - setToward(true); - } else { - cdiDegrees = Math.sign(courseDeviation) * -Avionics.Utils.diffAngle(180, Math.abs(courseDeviation)); - setToward(false); - } - setCdiPx(Math.min(12, Math.max(-12, cdiDegrees)) * 74 / 5); - }, [courseDeviation.toFixed(2)]); - - // we can't tell if the course is valid from the MSFS radio, so at least check that the frequency is - const vorCourseValid = vorFrequency > 0; - - // FIXME vor bearing - heading when course invalid - return ( - - - - - - - - { vorCourseValid && ( - <> - - - - )} - { available - && ( - <> - - - - - - )} - - ); -}; - -// TODO true ref -const IlsCaptureOverlay: React.FC<{ - heading: number, - side: EfisSide, -}> = memo(({ heading, side }) => { - const index = side === 'L' ? 2 : 1; - const [course] = useSimVar(`NAV OBS:${index + 2}`, 'degrees'); - const [ilsFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index + 2}`, 'megahertz'); - // FIXME this shit needs to be per-MMR - const [courseDeviation] = useSimVar('L:A32NX_RADIO_RECEIVER_LOC_DEVIATION', 'number', 20); - const [available] = useSimVar('L:A32NX_RADIO_RECEIVER_LOC_IS_VALID', 'number'); - const [cdiPx, setCdiPx] = useState(12); - - useEffect(() => { - // TODO back-course - const dots = Math.max(-2, Math.min(2, courseDeviation / 0.8)); - setCdiPx(dots * 74); - }, [courseDeviation.toFixed(2)]); - - // we can't tell if the course is valid from the MSFS radio, so at least check that the frequency is - const ilsCourseValid = ilsFrequency >= 108 && ilsFrequency <= 112; - - return ( - - - - - - - - { ilsCourseValid && ( - <> - - - - )} - { available - && ( - <> - - - - )} - - ); -}); - -const Plane: React.FC = () => ( - - - - - - -); - -const TrackBug: React.FC<{heading: number, track: number}> = memo(({ heading, track }) => { - const diff = getSmallestAngle(track, heading); - return ( - <> - - - - ); -}); - -// TODO true ref -const LsCourseBug: React.FC<{heading: number, lsCourse: number}> = ({ heading, lsCourse }) => { - if (lsCourse < 0) { - return null; - } - - const diff = getSmallestAngle(lsCourse, heading); - return ( - <> - - - - ); -}; - -const SelectedHeadingBug: React.FC<{heading: number, selected: number}> = ({ heading, selected }) => { - if (selected < 0) { - return null; - } - - const diff = getSmallestAngle(selected, heading); - return ( - <> - - - - ); -}; - -const VorInfo: FC<{side: EfisSide}> = memo(({ side }) => { - const index = side === 'R' ? 2 : 1; - - const [vorIdent] = useSimVar(`NAV IDENT:${index}`, 'string'); - const [vorFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index}`, 'megahertz'); - const [vorCourse] = useSimVar(`NAV OBS:${index}`, 'degrees'); - const [fm1Healthy] = useSimVar('L:A32NX_FM1_HEALTHY_DISCRETE', 'boolean'); - const [fm2Healthy] = useSimVar('L:A32NX_FM2_HEALTHY_DISCRETE', 'boolean'); - const fm1NavDiscrete = useArinc429Var('L:A32NX_FM1_NAV_DISCRETE'); - const fm2NavDiscrete = useArinc429Var('L:A32NX_FM2_NAV_DISCRETE'); - const [tuningMode, setTuningMode] = useState(''); - - const [freqInt, freqDecimal] = vorFrequency.toFixed(2).split('.', 2); - - useEffect(() => { - const bitIndex = 10 + index; - if ((!fm1Healthy && !fm2Healthy) || (!fm1NavDiscrete.isNormalOperation() && !fm2NavDiscrete.isNormalOperation())) { - setTuningMode('R'); - } else if (fm1NavDiscrete.getBitValueOr(bitIndex, false) || fm2NavDiscrete.getBitValueOr(bitIndex, false)) { - setTuningMode('M'); - } else { - setTuningMode(''); - } - }, [fm1Healthy, fm1NavDiscrete.value, fm1NavDiscrete.ssm, fm2Healthy, fm2NavDiscrete.value, fm2NavDiscrete.ssm]); - - const vorFrequencyValid = vorFrequency > 0; - // we can't tell if the course is valid from the MSFS radio, so at least check that the frequency is - const vorCourseValid = vorFrequencyValid; - - return ( - - - VOR - {index} - - - {vorFrequencyValid ? freqInt : '---'} - - . - {vorFrequencyValid ? freqDecimal : '--'} - - - CRS - - {vorCourseValid ? (`${Math.round(vorCourse)}`).padStart(3, '0') : '---'} - ° - - {tuningMode} - {vorIdent} - - ); -}); - -const IlsInfo: FC<{side: EfisSide}> = memo(({ side }) => { - const index = side === 'R' ? 1 : 2; - - const [ilsIdent] = useSimVar(`NAV IDENT:${index + 2}`, 'string'); - const [ilsFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index + 2}`, 'megahertz'); - const [ilsCourse] = useSimVar(`NAV OBS:${index + 2}`, 'degrees'); - const [fm1Healthy] = useSimVar('L:A32NX_FM1_HEALTHY_DISCRETE', 'boolean'); - const [fm2Healthy] = useSimVar('L:A32NX_FM2_HEALTHY_DISCRETE', 'boolean'); - const fm1NavDiscrete = useArinc429Var('L:A32NX_FM1_NAV_DISCRETE'); - const fm2NavDiscrete = useArinc429Var('L:A32NX_FM2_NAV_DISCRETE'); - const [tuningMode, setTuningMode] = useState(''); - - const [freqInt, freqDecimal] = ilsFrequency.toFixed(2).split('.', 2); - - useEffect(() => { - const bitIndex = 14 + index; - if ((!fm1Healthy && !fm2Healthy) || (!fm1NavDiscrete.isNormalOperation() && !fm2NavDiscrete.isNormalOperation())) { - setTuningMode('R'); - } else if (fm1NavDiscrete.getBitValueOr(bitIndex, false) || fm2NavDiscrete.getBitValueOr(bitIndex, false)) { - setTuningMode('M'); - } else { - setTuningMode(''); - } - }, [fm1Healthy, fm1NavDiscrete.value, fm1NavDiscrete.ssm, fm2Healthy, fm2NavDiscrete.value, fm2NavDiscrete.ssm]); - - const ilsFrequencyValid = ilsFrequency >= 108 && ilsFrequency <= 112; - // we can't tell if the course is valid from the MSFS radio, so at least check that the frequency is - const ilsCourseValid = ilsFrequencyValid; - - return ( - - - ILS - {index} - - - {ilsFrequencyValid ? freqInt : '---'} - - . - {ilsFrequencyValid ? freqDecimal : '--'} - - - CRS - - {ilsCourseValid ? (`${Math.round(ilsCourse)}`).padStart(3, '0') : '---'} - ° - - {tuningMode} - {ilsIdent} - - ); -}); - -const GlideSlope: FC = () => { - // TODO need some photo refs for this - // FIXME this shit needs to be per-MMR - const [gsDeviation] = useSimVar('L:A32NX_RADIO_RECEIVER_GS_DEVIATION', 'number'); - const [gsAvailable] = useSimVar('L:A32NX_RADIO_RECEIVER_GS_IS_VALID', 'number'); - - const deviationPx = gsDeviation / 0.8 * 128; - - return ( - <> - - - - - - - - - - -128) ? 'visible' : 'hidden'} - /> - - - ); -}; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx index c8bd37c07e1..0884ca0ecb8 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/AltitudeIndicator.tsx @@ -3,15 +3,14 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, DisplayComponent, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Register, Arinc429Word, Arinc429WordData, Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; + import { VerticalMode } from '@shared/autopilot'; -import { Arinc429RegisterSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { DigitalAltitudeReadout } from './DigitalAltitudeReadout'; import { SimplaneValues } from './shared/SimplaneValueProvider'; import { VerticalTape } from './VerticalTape'; import { Arinc429Values } from './shared/ArincValueProvider'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; const DisplayRange = 570; const ValueSpacing = 100; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx index 3f7505c8bc8..fcdcd5aacf5 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorFixed.tsx @@ -3,13 +3,13 @@ // SPDX-License-Identifier: GPL-3.0 import { DisplayComponent, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + import { getDisplayIndex } from 'instruments/src/PFD/PFD'; import { FlightPathDirector } from './FlightPathDirector'; import { FlightPathVector } from './FlightPathVector'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; interface AttitudeIndicatorFixedUpperProps { bus: ArincEventBus; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx index 545566ca58b..ef7505ec08d 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/AttitudeIndicatorHorizon.tsx @@ -3,9 +3,8 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, ConsumerSubject, DisplayComponent, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Register, Arinc429Word, Arinc429WordData, Arinc429RegisterSubject, Arinc429ConsumerSubject } from '@flybywiresim/fbw-sdk'; -import { Arinc429RegisterSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject'; import { DmcLogicEvents } from '../MsfsAvionicsCommon/providers/DmcPublisher'; import { calculateHorizonOffsetFromPitch, @@ -17,8 +16,6 @@ import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { Arinc429Values } from './shared/ArincValueProvider'; import { HorizontalTape } from './HorizontalTape'; import { getDisplayIndex } from './PFD'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; -import { Arinc429ConsumerSubject } from '../MsfsAvionicsCommon/Arinc429ConsumerSubject'; const DisplayRange = 35; const DistanceSpacing = 15; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/DigitalAltitudeReadout.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/DigitalAltitudeReadout.tsx index a0781ecad42..f454389cac9 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/DigitalAltitudeReadout.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/DigitalAltitudeReadout.tsx @@ -3,11 +3,11 @@ // SPDX-License-Identifier: GPL-3.0 import { ConsumerSubject, DisplayComponent, FSComponent, MappedSubject, NodeReference, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429RegisterSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject'; +import { ArincEventBus, Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; + import { SimplaneBaroMode, SimplaneValues } from 'instruments/src/PFD/shared/SimplaneValueProvider'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; const TensDigits = (value: number) => { let text: string; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx index fe29325e32f..e36a5cc6914 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/FMA.tsx @@ -3,13 +3,11 @@ // SPDX-License-Identifier: GPL-3.0 import { ComponentProps, DisplayComponent, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { ArmedLateralMode, ArmedVerticalMode, isArmed, LateralMode, VerticalMode } from '@shared/autopilot'; +import { ArincEventBus, Arinc429Word, Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; -import { Arinc429Word } from '@flybywiresim/fbw-sdk'; -import { Arinc429RegisterSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject'; +import { ArmedLateralMode, ArmedVerticalMode, isArmed, LateralMode, VerticalMode } from '@shared/autopilot'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; abstract class ShowForSecondsComponent extends DisplayComponent { private timeout: number = 0; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx index 4880dc08cc8..b872c09a2d8 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathDirector.tsx @@ -3,12 +3,12 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, DisplayComponent, FSComponent, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + import { getDisplayIndex } from './PFD'; import { calculateHorizonOffsetFromPitch } from './PFDUtils'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; const DistanceSpacing = 15; const ValueSpacing = 10; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx index 018a50dda14..460ccb4da18 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/FlightPathVector.tsx @@ -3,8 +3,8 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, DisplayComponent, FSComponent, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; +import { ArincEventBus, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + import { calculateHorizonOffsetFromPitch } from './PFDUtils'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx index bc3d9046696..d18cb7c51eb 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/HeadingIndicator.tsx @@ -1,11 +1,16 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { DisplayComponent, FSComponent, HEvent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; +import { ArincEventBus } from '@flybywiresim/fbw-sdk'; + import { DmcLogicEvents } from '../MsfsAvionicsCommon/providers/DmcPublisher'; import { HorizontalTape } from './HorizontalTape'; import { getSmallestAngle } from './PFDUtils'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { Arinc429Values } from './shared/ArincValueProvider'; import { getDisplayIndex } from './PFD'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; const DisplayRange = 24; const DistanceSpacing = 7.555; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/HorizontalTape.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/HorizontalTape.tsx index 1ecde6fdad1..7fa15f4ab78 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/HorizontalTape.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/HorizontalTape.tsx @@ -1,7 +1,12 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { DisplayComponent, FSComponent, NodeReference, VNode, Subscribable } from '@microsoft/msfs-sdk'; +import { ArincEventBus } from '@flybywiresim/fbw-sdk'; + import { DmcLogicEvents } from '../MsfsAvionicsCommon/providers/DmcPublisher'; import { Arinc429Values } from './shared/ArincValueProvider'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; interface HorizontalTapeProps { displayRange: number; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/LandingSystemIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/LandingSystemIndicator.tsx index 18c57578511..b6f17e25fe2 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/LandingSystemIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/LandingSystemIndicator.tsx @@ -3,12 +3,12 @@ // SPDX-License-Identifier: GPL-3.0 import { ConsumerSubject, DisplayComponent, FSComponent, HEvent, MappedSubject, MathUtils, Subject, Subscribable, SubscribableMapFunctions, Subscription, VNode } from '@microsoft/msfs-sdk'; +import { ArincEventBus, Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; + import { getDisplayIndex } from 'instruments/src/PFD/PFD'; -import { Arinc429RegisterSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject'; import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { LagFilter } from './PFDUtils'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; // FIXME true ref export class LandingSystem extends DisplayComponent<{ bus: ArincEventBus, instrument: BaseInstrument }> { diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/PFD.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/PFD.tsx index b2e2783d299..6a3aa8df737 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/PFD.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/PFD.tsx @@ -2,9 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0 -import { A320Failure, FailuresConsumer } from '@failures'; import { ClockEvents, ComponentProps, DisplayComponent, FSComponent, Subject, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + +import { A320Failure, FailuresConsumer } from '@failures'; import { DmcLogicEvents } from '../MsfsAvionicsCommon/providers/DmcPublisher'; import { LagFilter } from './PFDUtils'; import { Arinc429Values } from './shared/ArincValueProvider'; @@ -20,7 +21,6 @@ import { LinearDeviationIndicator } from './LinearDeviationIndicator'; import { AirspeedIndicator, AirspeedIndicatorOfftape, MachNumber } from './SpeedIndicator'; import { VerticalSpeedIndicator } from './VerticalSpeedIndicator'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; export const getDisplayIndex = () => { const url = document.getElementsByTagName('a32nx-pfd')[0].getAttribute('url'); diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx index 08af7ad38ea..06fe6f47a5a 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/SpeedIndicator.tsx @@ -3,13 +3,13 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, DisplayComponent, FSComponent, NodeReference, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + import { FmsVars } from 'instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { VerticalTape } from './VerticalTape'; import { SimplaneValues } from './shared/SimplaneValueProvider'; import { Arinc429Values } from './shared/ArincValueProvider'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; const ValueSpacing = 10; const DistanceSpacing = 10; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx index de0f3f05dd7..8da8ae83490 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/VerticalSpeedIndicator.tsx @@ -3,11 +3,11 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, ComponentProps, DisplayComponent, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429Word } from '@flybywiresim/fbw-sdk'; +import { ArincEventBus, Arinc429Word } from '@flybywiresim/fbw-sdk'; + import { Arinc429Values } from './shared/ArincValueProvider'; import { PFDSimvars } from './shared/PFDSimvarPublisher'; import { LagFilter } from './PFDUtils'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; interface VerticalSpeedIndicatorProps { bus: ArincEventBus, diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx index bec2c2124b7..a991c458f61 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/instrument.tsx @@ -1,4 +1,10 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { Clock, FSComponent, HEventPublisher, Subject } from '@microsoft/msfs-sdk'; +import { ArincEventBus } from '@flybywiresim/fbw-sdk'; + import { DmcPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; import { FmsDataPublisher } from 'instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher'; import { getDisplayIndex, PFDComponent } from './PFD'; @@ -6,7 +12,6 @@ import { AdirsValueProvider } from '../MsfsAvionicsCommon/AdirsValueProvider'; import { ArincValueProvider } from './shared/ArincValueProvider'; import { PFDSimvarPublisher, PFDSimvars } from './shared/PFDSimvarPublisher'; import { SimplaneValueProvider } from './shared/SimplaneValueProvider'; -import { ArincEventBus } from '../MsfsAvionicsCommon/ArincEventBus'; import './style.scss'; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/shared/ArincValueProvider.ts b/fbw-a32nx/src/systems/instruments/src/PFD/shared/ArincValueProvider.ts index c61ad02605a..094919590e2 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/shared/ArincValueProvider.ts +++ b/fbw-a32nx/src/systems/instruments/src/PFD/shared/ArincValueProvider.ts @@ -3,10 +3,10 @@ // SPDX-License-Identifier: GPL-3.0 import { ConsumerSubject, MathUtils, Publisher, Subscription } from '@microsoft/msfs-sdk'; +import { ArincEventBus, Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + import { getDisplayIndex } from 'instruments/src/PFD/PFD'; -import { Arinc429Register, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk'; import { PFDSimvars } from './PFDSimvarPublisher'; -import { ArincEventBus } from '../../MsfsAvionicsCommon/ArincEventBus'; export interface Arinc429Values { pitchAr: Arinc429WordData; diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx b/fbw-a32nx/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx index 38c7f06c712..62451938182 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx +++ b/fbw-a32nx/src/systems/instruments/src/PFD/shared/PFDSimvarPublisher.tsx @@ -1,10 +1,15 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { SimVarDefinition, SimVarValueType } from '@microsoft/msfs-sdk'; +import { ArincEventBus } from '@flybywiresim/fbw-sdk'; + import { AdirsSimVarDefinitions, AdirsSimVars, SwitchingPanelSimVarsDefinitions, SwitchingPanelVSimVars, } from '../../MsfsAvionicsCommon/SimVarTypes'; -import { ArincEventBus } from '../../MsfsAvionicsCommon/ArincEventBus'; import { UpdatableSimVarPublisher } from '../../MsfsAvionicsCommon/UpdatableSimVarPublisher'; export type PFDSimvars = AdirsSimVars & SwitchingPanelVSimVars & { diff --git a/fbw-a32nx/src/systems/instruments/src/PFD/shared/SimplaneValueProvider.ts b/fbw-a32nx/src/systems/instruments/src/PFD/shared/SimplaneValueProvider.ts index 3b36bb1f663..13d099fb57e 100644 --- a/fbw-a32nx/src/systems/instruments/src/PFD/shared/SimplaneValueProvider.ts +++ b/fbw-a32nx/src/systems/instruments/src/PFD/shared/SimplaneValueProvider.ts @@ -1,6 +1,9 @@ -import { Publisher } from '@microsoft/msfs-sdk'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 -import { ArincEventBus } from 'instruments/src/MsfsAvionicsCommon/ArincEventBus'; +import { Publisher } from '@microsoft/msfs-sdk'; +import { ArincEventBus } from '@flybywiresim/fbw-sdk'; export type SimplaneBaroMode = 'QNH' | 'QFE' | 'STD'; diff --git a/fbw-a380x/.env b/fbw-a380x/.env new file mode 100644 index 00000000000..c7304412e55 --- /dev/null +++ b/fbw-a380x/.env @@ -0,0 +1,5 @@ +VITE_BUILD=false +NODE_ENV=production +CLIENT_SECRET="" +CLIENT_ID="" +SENTRY_DSN="" diff --git a/fbw-a380x/mach.config.js b/fbw-a380x/mach.config.js index 40f56dd3e6e..c6d199fb6fd 100644 --- a/fbw-a380x/mach.config.js +++ b/fbw-a380x/mach.config.js @@ -29,6 +29,7 @@ module.exports = { ], instruments: [ msfsAvionicsInstrument('PFD'), + msfsAvionicsInstrument('ND'), reactInstrument('EWD'), reactInstrument('MFD'), diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/JS/fbw-a380x/A380X_Simvars.js b/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/JS/fbw-a380x/A380X_Simvars.js new file mode 100644 index 00000000000..3501089212b --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/html_ui/JS/fbw-a380x/A380X_Simvars.js @@ -0,0 +1,93 @@ +/** + * taken from the AAU1 G3000 + * The purpose is to reduce the amount of string allocations caused by `.toLowerCase()` + */ + +const latlonaltRegEx = /^latlonalt$/i; +const latlonaltpbhRegex = /^latlonaltpbh$/i; +const pbhRegex = /^pbh$/i; +const pid_structRegex = /^pid_struct$/i; +const xyzRegex = /^xyz$/i; +const stringRegex = /^string$/i; +const boolRegex = /^boolean$|^bool$/i; +const numberRegex = /^number$/i; +const defaultSource = ''; + +SimVar.GetSimVarValue = (name, unit, dataSource = defaultSource) => { + try { + if (simvar) { + let output; + const registeredID = SimVar.GetRegisteredId(name, unit, dataSource); + + if (registeredID >= 0) { + if (numberRegex.test(unit)) { + output = simvar.getValueReg(registeredID); + } else if (stringRegex.test(unit)) { + output = simvar.getValueReg_String(registeredID); + } else if (latlonaltRegEx.test(unit)) { + output = new LatLongAlt(simvar.getValue_LatLongAlt(name, dataSource)); + } else if (latlonaltpbhRegex.test(unit)) { + output = new LatLongAltPBH(simvar.getValue_LatLongAltPBH(name, dataSource)); + } else if (pbhRegex.test(unit)) { + output = new PitchBankHeading(simvar.getValue_PBH(name, dataSource)); + } else if (pid_structRegex.test(unit)) { + output = new PID_STRUCT(simvar.getValue_PID_STRUCT(name, dataSource)); + } else if (xyzRegex.test(unit)) { + output = new XYZ(simvar.getValue_XYZ(name, dataSource)); + } else { + output = simvar.getValueReg(registeredID); + } + } + return output; + } + console.warn(`SimVar handler is not defined (${name})`); + } catch (error) { + console.warn('ERROR ', error, ` GetSimVarValue ${name} unit : ${unit}`); + return null; + } + return null; +}; +SimVar.SetSimVarValue = (name, unit, value, dataSource = defaultSource) => { + if (value == undefined) { + console.warn(`${name} : Trying to set a null value`); + return Promise.resolve(); + } + try { + if (simvar) { + const regID = SimVar.GetRegisteredId(name, unit, dataSource); + if (regID >= 0) { + if (stringRegex.test(unit)) { + return Coherent.call('setValueReg_String', regID, value); + } + if (boolRegex.test(unit)) { + return Coherent.call('setValueReg_Bool', regID, !!value); + } + if (numberRegex.test(unit)) { + return Coherent.call('setValueReg_Number', regID, value); + } + if (latlonaltRegEx.test(unit)) { + return Coherent.call('setValue_LatLongAlt', name, value, dataSource); + } + if (latlonaltpbhRegex.test(unit)) { + return Coherent.call('setValue_LatLongAltPBH', name, value, dataSource); + } + if (pbhRegex.test(unit)) { + return Coherent.call('setValue_PBH', name, value, dataSource); + } + if (pid_structRegex.test(unit)) { + return Coherent.call('setValue_PID_STRUCT', name, value, dataSource); + } + if (xyzRegex.test(unit)) { + return Coherent.call('setValue_XYZ', name, value, dataSource); + } + + return Coherent.call('setValueReg_Number', regID, value); + } + } else { + console.warn('SimVar handler is not defined'); + } + } catch (error) { + console.warn(`error SetSimVarValue ${error}`); + } + return Promise.resolve(); +}; diff --git a/fbw-a380x/src/systems/instruments/src/.eslintrc b/fbw-a380x/src/systems/instruments/src/.eslintrc new file mode 100644 index 00000000000..aad9571180f --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/.eslintrc @@ -0,0 +1,10 @@ +{ + "overrides": [ + { + "files": ["util.js"], + "parserOptions": { + "sourceType": "module" + } + } + ] +} diff --git a/fbw-a380x/src/systems/instruments/src/Common/CdsDisplayUnit.tsx b/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx similarity index 97% rename from fbw-a380x/src/systems/instruments/src/Common/CdsDisplayUnit.tsx rename to fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx index 0deec937fe5..49c97290671 100644 --- a/fbw-a380x/src/systems/instruments/src/Common/CdsDisplayUnit.tsx +++ b/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx @@ -62,7 +62,7 @@ function BacklightBleed(props) { return
; } -export const CdsDisplayUnit = forwardRef>(({ displayUnitId, failed, children }, ref) => { +export const LegacyCdsDisplayUnit = forwardRef>(({ displayUnitId, failed, children }, ref) => { const [coldDark] = useSimVar('L:A32NX_COLD_AND_DARK_SPAWN' /* TODO 380 simvar */, 'Bool', 200); const [state, setState] = useState((coldDark) ? DisplayUnitState.Off : DisplayUnitState.Standby); const [timer, setTimer] = useState(null); diff --git a/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx b/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx index 5315f6ea468..c3934adbe1c 100644 --- a/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx +++ b/fbw-a380x/src/systems/instruments/src/EWD/EngineWarningDisplay.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { CdsDisplayUnit, DisplayUnitID } from '@instruments/common/CdsDisplayUnit'; +import { LegacyCdsDisplayUnit, DisplayUnitID } from '@instruments/common/LegacyCdsDisplayUnit'; import { useSimVar } from '@instruments/common/simVars'; import { EngineGauge } from './elements/EngineGauge'; import ThrustRatingMode from './elements/ThrustRatingMode'; @@ -24,7 +24,7 @@ export const EngineWarningDisplay: React.FC = () => { const displayMemo = true; return ( - + @@ -58,6 +58,6 @@ export const EngineWarningDisplay: React.FC = () => { {/* */} - + ); }; diff --git a/fbw-a380x/src/systems/instruments/src/MFD/MultiFunctionDisplay.tsx b/fbw-a380x/src/systems/instruments/src/MFD/MultiFunctionDisplay.tsx index 6cb2265f645..dcae2c25655 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/MultiFunctionDisplay.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/MultiFunctionDisplay.tsx @@ -5,7 +5,7 @@ import React, { FC, useRef, useState } from 'react'; import { Redirect, Route, Switch, useHistory } from 'react-router-dom'; import { FlightPlanProvider } from '@instruments/common/flightplan'; import { Position } from '@instruments/common/types'; -import { CdsDisplayUnit, DisplayUnitID } from '@instruments/common/CdsDisplayUnit'; +import { LegacyCdsDisplayUnit, DisplayUnitID } from '@instruments/common/LegacyCdsDisplayUnit'; import { GuidanceController } from '@fmgc/guidance/GuidanceController'; import { useUpdate } from '@instruments/common/hooks'; import { EfisSymbols } from '@fmgc/efis/EfisSymbols'; @@ -55,7 +55,7 @@ export const MultiFunctionDisplay: FC = ({ displayUni return ( - + @@ -77,7 +77,7 @@ export const MultiFunctionDisplay: FC = ({ displayUni {!hideCursor && } - + ); }; diff --git a/fbw-a380x/src/systems/instruments/src/MFD/index.tsx b/fbw-a380x/src/systems/instruments/src/MFD/index.tsx index a423f1a1c40..42f74a96e18 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/index.tsx @@ -6,7 +6,7 @@ import '../index.scss'; import { FlightPlanService } from '@fmgc/flightplanning/new/FlightPlanService'; import { NavigationDatabase, NavigationDatabaseBackend } from '@fmgc/NavigationDatabase'; import { NavigationDatabaseService } from '@fmgc/flightplanning/new/NavigationDatabaseService'; -import { DisplayUnitID } from '@instruments/common/CdsDisplayUnit'; +import { DisplayUnitID } from '@instruments/common/LegacyCdsDisplayUnit'; import { render } from '../Common'; import { MultiFunctionDisplay } from './MultiFunctionDisplay'; import { renderTarget } from '../util.js'; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/.eslintrc.js b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/.eslintrc.js new file mode 100644 index 00000000000..531906dff5b --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/.eslintrc.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = { + + extends: '../.eslintrc', + + // overrides airbnb, use sparingly + rules: { 'react/no-unknown-property': 'off', 'react/style-prop-object': 'off' }, + +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx new file mode 100644 index 00000000000..f10f8141b5f --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/AdirsValueProvider.tsx @@ -0,0 +1,59 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { SimVarValueType } from '@microsoft/msfs-sdk'; +import { ArincEventBus, EfisSide } from '@flybywiresim/fbw-sdk'; + +import { AdirsSimVars, SwitchingPanelVSimVars } from './SimVarTypes'; +import { UpdatableSimVarPublisher } from './UpdatableSimVarPublisher'; + +export class AdirsValueProvider { + constructor( + private readonly bus: ArincEventBus, + private readonly varProvider: UpdatableSimVarPublisher, + private readonly displaySide: EfisSide, + ) { + } + + public start() { + const sub = this.bus.getSubscriber(); + + const displayIndex = this.displaySide === 'R' ? 2 : 1; + + sub.on('attHdgKnob').whenChanged().handle((knobPosition) => { + const inertialSource = getSupplier(this.displaySide, knobPosition); + this.varProvider.updateSimVarSource('latitude', { name: `L:A32NX_ADIRS_IR_${inertialSource}_LATITUDE`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('longitude', { name: `L:A32NX_ADIRS_IR_${inertialSource}_LONGITUDE`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('vsInert', { name: `L:A32NX_ADIRS_IR_${inertialSource}_VERTICAL_SPEED`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('pitch', { name: `L:A32NX_ADIRS_IR_${inertialSource}_PITCH`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('roll', { name: `L:A32NX_ADIRS_IR_${inertialSource}_ROLL`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('magHeadingRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_HEADING`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('magTrackRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_TRACK`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('fpaRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_FLIGHT_PATH_ANGLE`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('daRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_DRIFT_ANGLE`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('latAccRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_BODY_LATERAL_ACC`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('irMaintWordRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_MAINT_WORD`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('trueHeadingRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_TRUE_HEADING`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('trueTrackRaw', { name: `L:A32NX_ADIRS_IR_${inertialSource}_TRUE_TRACK`, type: SimVarValueType.Number }); + }); + + sub.on('airKnob').whenChanged().handle((knobPosition) => { + const airSource = getSupplier(this.displaySide, knobPosition); + this.varProvider.updateSimVarSource('speed', { name: `L:A32NX_ADIRS_ADR_${airSource}_COMPUTED_AIRSPEED`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('vsBaro', { name: `L:A32NX_ADIRS_ADR_${airSource}_BAROMETRIC_VERTICAL_SPEED`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('baroCorrectedAltitude', { name: `L:A32NX_ADIRS_ADR_${airSource}_BARO_CORRECTED_ALTITUDE_${displayIndex}`, type: SimVarValueType.Number }); + this.varProvider.updateSimVarSource('mach', { name: `L:A32NX_ADIRS_ADR_${airSource}_MACH`, type: SimVarValueType.Number }); + }); + } +} + +const getSupplier = (displaySide: EfisSide, knobValue: number) => { + const adirs3ToCaptain = 0; + const adirs3ToFO = 2; + + if (displaySide === 'L') { + return knobValue === adirs3ToCaptain ? 3 : 1; + } + return knobValue === adirs3ToFO ? 3 : 2; +}; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/CdsDisplayUnit.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/CdsDisplayUnit.tsx new file mode 100644 index 00000000000..fa135f35678 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/CdsDisplayUnit.tsx @@ -0,0 +1,278 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { + ClockEvents, + DisplayComponent, + EventBus, + FSComponent, MappedSubject, + Subject, + Subscribable, + VNode +} from '@microsoft/msfs-sdk'; +import { NXDataStore } from '@flybywiresim/fbw-sdk'; +// import { getSupplier } from '@flybywiresim/fbw-sdk'; +import { DisplayVars } from './SimVarTypes'; +import { DcElectricalBus } from "@shared/electrical"; + +import './common.scss'; + +export const getDisplayIndex = () => { + const url = Array.from(document.querySelectorAll('vcockpit-panel > *')) + .find((it) => it.tagName.toLowerCase() !== 'wasm-instrument') + .getAttribute('url'); + + return url ? parseInt(url.substring(url.length - 1), 10) : 0; +}; + +export enum DisplayUnitID { + CaptPfd, + CaptNd, + CaptMfd, + FoPfd, + FoNd, + FoMfd, + Ewd, + Sd, +} + +const DisplayUnitToDCBus: { [k in DisplayUnitID]: DcElectricalBus[] } = { + [DisplayUnitID.CaptPfd]: [DcElectricalBus.DcEss], + [DisplayUnitID.CaptNd]: [DcElectricalBus.DcEss, DcElectricalBus.Dc1], + [DisplayUnitID.CaptMfd]: [DcElectricalBus.DcEss, DcElectricalBus.Dc1], + [DisplayUnitID.FoPfd]: [DcElectricalBus.Dc2], + [DisplayUnitID.FoNd]: [DcElectricalBus.Dc1, DcElectricalBus.Dc2], + [DisplayUnitID.FoMfd]: [DcElectricalBus.Dc1, DcElectricalBus.Dc2], + [DisplayUnitID.Ewd]: [DcElectricalBus.DcEss], + [DisplayUnitID.Sd]: [DcElectricalBus.Dc2], +}; + +const DisplayUnitToPotentiometer: { [k in DisplayUnitID]: number } = { + [DisplayUnitID.CaptPfd]: 88, + [DisplayUnitID.CaptNd]: 89, + [DisplayUnitID.CaptMfd]: 98, + [DisplayUnitID.FoPfd]: 90, + [DisplayUnitID.FoNd]: 91, + [DisplayUnitID.FoMfd]: 99, + [DisplayUnitID.Ewd]: 92, + [DisplayUnitID.Sd]: 93, +}; + +interface DisplayUnitProps { + bus: EventBus, + displayUnitId: DisplayUnitID, + failed?: Subscribable, + test?: Subscribable, +} + +enum DisplayUnitState { + On, + MaintenanceMode, + EngineeringTest, + Off, + ThalesBootup, + Selftest, + Standby +} + +export class CdsDisplayUnit extends DisplayComponent { + private state: DisplayUnitState = SimVar.GetSimVarValue('L:A32NX_COLD_AND_DARK_SPAWN', 'Bool') ? DisplayUnitState.Off : DisplayUnitState.Standby; + + private timeOut: number = 0; + + private selfTestRef = FSComponent.createRef(); + + private thalesBootupRef = FSComponent.createRef(); + + private maintenanceModeRef = FSComponent.createRef(); + + private engineeringTestModeRef = FSComponent.createRef(); + + private pfdRef = FSComponent.createRef(); + + // private supplyingDmc: number = 3; + + private readonly brightness = Subject.create(0); + + private failed = false; + + private readonly powered = Subject.create(false); + + public onAfterRender(node: VNode): void { + super.onAfterRender(node); + + const sub = this.props.bus.getSubscriber(); + + sub.on('realTime').handle(() => this.update()); + sub.on('realTime').atFrequency(1).handle((_t) => { + // override MSFS menu animations setting for this instrument + if (!document.documentElement.classList.contains('animationsEnabled')) { + document.documentElement.classList.add('animationsEnabled'); + } + }); + + MappedSubject.create(() => { + this.updateState(); + }, this.brightness, this.powered); + + this.props.failed?.sub((f) => { + this.failed = f; + this.updateState(); + }, true); + } + + setTimer(time: number) { + this.timeOut = window.setTimeout(() => { + if (this.state === DisplayUnitState.Standby) { + this.state = DisplayUnitState.Off; + } + if (this.state === DisplayUnitState.Selftest) { + this.state = DisplayUnitState.On; + } + this.updateState(); + }, time * 1000); + } + + // TODO: Fix and reenable + /* + checkMaintMode() { + const dmcKnob = SimVar.GetSimVarValue('L:A32NX_EIS_DMC_SWITCHING_KNOB', 'Enum'); + this.supplyingDmc = getSupplier(this.props.normDmc, dmcKnob); + const dmcDisplayTestMode = SimVar.GetSimVarValue(`L:A32NX_DMC_DISPLAYTEST:${this.supplyingDmc}`, 'Enum'); + switch (dmcDisplayTestMode) { + case 1: + this.state = DisplayUnitState.MaintenanceMode; + break; + case 2: + this.state = DisplayUnitState.EngineeringTest; + break; + default: + this.state = DisplayUnitState.On; + } + } + */ + + public update() { + const potentiometer = SimVar.GetSimVarValue(`LIGHT POTENTIOMETER:${DisplayUnitToPotentiometer[this.props.displayUnitId]}`, 'percent over 100'); + const poweredByBus1 = SimVar.GetSimVarValue(`L:A32NX_ELEC_${DisplayUnitToDCBus[this.props.displayUnitId][0]}_BUS_IS_POWERED`, 'Bool'); + const poweredByBus2 = SimVar.GetSimVarValue(`L:A32NX_ELEC_${DisplayUnitToDCBus[this.props.displayUnitId][1]}_BUS_IS_POWERED`, 'Bool'); + + this.brightness.set(potentiometer); + this.powered.set(poweredByBus1 || poweredByBus2); + } + + updateState() { + if (this.state !== DisplayUnitState.Off && this.failed) { + this.state = DisplayUnitState.Off; + clearTimeout(this.timeOut); + } else if (this.state === DisplayUnitState.On && (this.brightness.get() === 0 || !this.powered.get())) { + this.state = DisplayUnitState.Standby; + this.setTimer(10); + } else if (this.state === DisplayUnitState.Standby && (this.brightness.get() !== 0 && this.powered.get())) { + this.state = DisplayUnitState.On; + clearTimeout(this.timeOut); + } else if (this.state === DisplayUnitState.Off && (this.brightness.get() !== 0 && this.powered.get() && !this.failed)) { + this.state = DisplayUnitState.ThalesBootup; + this.setTimer(0.25 + (Math.random() * 0.2)); + } else if (this.state === DisplayUnitState.ThalesBootup && (this.brightness.get() !== 0 && this.powered.get() && !this.failed)) { + this.state = DisplayUnitState.Selftest; + this.setTimer(parseInt(NXDataStore.get('CONFIG_SELF_TEST_TIME', '15'))); + } else if ((this.state === DisplayUnitState.Selftest || this.state === DisplayUnitState.ThalesBootup) && (this.brightness.get() === 0 || !this.powered.get())) { + this.state = DisplayUnitState.Off; + clearTimeout(this.timeOut); + } + + if (this.state === DisplayUnitState.Selftest) { + this.selfTestRef.instance.style.display = 'block'; + this.thalesBootupRef.instance.style.display = 'none'; + this.maintenanceModeRef.instance.style.display = 'none'; + this.engineeringTestModeRef.instance.style.display = 'none'; + this.pfdRef.instance.style.display = 'none'; + } else if (this.state === DisplayUnitState.ThalesBootup) { + this.selfTestRef.instance.style.display = 'none'; + this.thalesBootupRef.instance.style.display = 'block'; + this.maintenanceModeRef.instance.style.display = 'none'; + this.engineeringTestModeRef.instance.style.display = 'none'; + this.pfdRef.instance.style.display = 'none'; + } else if (this.state === DisplayUnitState.On) { + this.selfTestRef.instance.style.display = 'none'; + this.thalesBootupRef.instance.style.display = 'none'; + this.maintenanceModeRef.instance.style.display = 'none'; + this.engineeringTestModeRef.instance.style.display = 'none'; + this.pfdRef.instance.style.display = 'block'; + } else if (this.state === DisplayUnitState.MaintenanceMode) { + this.selfTestRef.instance.style.display = 'none'; + this.thalesBootupRef.instance.style.display = 'none'; + this.maintenanceModeRef.instance.style.display = 'block'; + this.engineeringTestModeRef.instance.style.display = 'none'; + this.pfdRef.instance.style.display = 'none'; + } else if (this.state === DisplayUnitState.EngineeringTest) { + this.selfTestRef.instance.style.display = 'none'; + this.thalesBootupRef.instance.style.display = 'none'; + this.maintenanceModeRef.instance.style.display = 'none'; + this.engineeringTestModeRef.instance.style.display = 'block'; + this.pfdRef.instance.style.display = 'none'; + } else { + this.selfTestRef.instance.style.display = 'none'; + this.thalesBootupRef.instance.style.display = 'none'; + this.maintenanceModeRef.instance.style.display = 'none'; + this.engineeringTestModeRef.instance.style.display = 'none'; + this.pfdRef.instance.style.display = 'none'; + } + } + + render(): VNode { + return ( + <> + + + + + + + + +
{this.props.children}
+ + + ); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/Layer.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/Layer.tsx new file mode 100644 index 00000000000..29609e8210c --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/Layer.tsx @@ -0,0 +1,29 @@ +import { FSComponent, DisplayComponent, VNode, Subscribable, MappedSubject, ComponentProps } from '@microsoft/msfs-sdk'; + +export interface LayerProps extends ComponentProps { + x: number | Subscribable; + y: number | Subscribable; + visible?: Subscribable; +} + +export class Layer extends DisplayComponent { + render(): VNode | null { + const { x, y } = this.props; + const ref = this.props.ref ?? FSComponent.createRef(); + + let value: Subscribable | string; + if (typeof x !== 'number' && typeof y !== 'number') { + value = MappedSubject.create(([x, y]) => `translate(${x}, ${y})`, x, y); + } else if (typeof x !== 'number' || typeof y !== 'number') { + throw new Error('Both attributes of Layer must be of the same type (number or Subscribable)'); + } else { + value = `translate(${x}, ${y})`; + } + + return ( + (v ? 'inherit' : 'hidden')) ?? 'inherit'}> + {this.props.children} + + ); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/SimVarTypes.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/SimVarTypes.ts new file mode 100644 index 00000000000..79a0eeab6c6 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/SimVarTypes.ts @@ -0,0 +1,94 @@ +import { SimVarDefinition, SimVarValueType } from '@microsoft/msfs-sdk'; + +export interface DisplayVars { + elec: number; + elecFo: number; + potentiometerCaptain: number; + potentiometerFo: number; +} + +export interface AdirsSimVars { + pitch: number; + roll: number; + magHeadingRaw: number; + baroCorrectedAltitude: number; + speed: number; + vsInert: number; + vsBaro: number; + magTrackRaw: number; + groundSpeed: number; + trueAirSpeed: number; + windDirection: number; + windSpeed: number; + fpaRaw: number; + daRaw: number; + mach: number; + latitude: number; + longitude: number; + latAccRaw: number; + irMaintWordRaw: number; + trueHeadingRaw: number; + trueTrackRaw: number; +} + +export enum AdirsVars { + pitch = 'L:A32NX_ADIRS_IR_1_PITCH', + roll = 'L:A32NX_ADIRS_IR_1_ROLL', + magHeadingRaw = 'L:A32NX_ADIRS_IR_1_HEADING', + trueHeadingRaw = 'L:A32NX_ADIRS_IR_1_TRUE_HEADING', + baroCorrectedAltitude1 = 'L:A32NX_ADIRS_ADR_1_BARO_CORRECTED_ALTITUDE_1', + speed = 'L:A32NX_ADIRS_ADR_1_COMPUTED_AIRSPEED', + vsInert = 'L:A32NX_ADIRS_IR_1_VERTICAL_SPEED', + vsBaro = 'L:A32NX_ADIRS_ADR_1_BAROMETRIC_VERTICAL_SPEED', + magTrackRaw = 'L:A32NX_ADIRS_IR_1_TRACK', + trueTrackRaw = 'L:A32NX_ADIRS_IR_1_TRUE_TRACK', + groundSpeed = 'L:A32NX_ADIRS_IR_1_GROUND_SPEED', + trueAirSpeed = 'L:A32NX_ADIRS_ADR_1_TRUE_AIRSPEED', + windDirection = 'L:A32NX_ADIRS_IR_1_WIND_DIRECTION_BNR', + windSpeed = 'L:A32NX_ADIRS_IR_1_WIND_SPEED_BNR', + fpaRaw = 'L:A32NX_ADIRS_IR_1_FLIGHT_PATH_ANGLE', + daRaw = 'L:A32NX_ADIRS_IR_1_DRIFT_ANGLE', + mach = 'L:A32NX_ADIRS_ADR_1_MACH', + latitude = 'L:A32NX_ADIRS_IR_1_LATITUDE', + longitude = 'L:A32NX_ADIRS_IR_1_LONGITUDE', + irMaintWordRaw = 'L:A32NX_ADIRS_IR_1_MAINT_WORD', +} + +export const AdirsSimVarDefinitions = new Map([ + ['pitch', { name: AdirsVars.pitch, type: SimVarValueType.Number }], + ['roll', { name: AdirsVars.roll, type: SimVarValueType.Number }], + ['magHeadingRaw', { name: AdirsVars.magHeadingRaw, type: SimVarValueType.Number }], + ['trueHeadingRaw', { name: AdirsVars.trueHeadingRaw, type: SimVarValueType.Number }], + ['baroCorrectedAltitude', { name: AdirsVars.baroCorrectedAltitude1, type: SimVarValueType.Number }], + ['speed', { name: AdirsVars.speed, type: SimVarValueType.Number }], + ['magTrackRaw', { name: AdirsVars.magTrackRaw, type: SimVarValueType.Number }], + ['trueTrackRaw', { name: AdirsVars.trueTrackRaw, type: SimVarValueType.Number }], + ['groundSpeed', { name: AdirsVars.groundSpeed, type: SimVarValueType.Number }], + ['trueAirSpeed', { name: AdirsVars.trueAirSpeed, type: SimVarValueType.Number }], + ['windDirection', { name: AdirsVars.windDirection, type: SimVarValueType.Number }], + ['windSpeed', { name: AdirsVars.windSpeed, type: SimVarValueType.Number }], + ['fpaRaw', { name: AdirsVars.fpaRaw, type: SimVarValueType.Number }], + ['daRaw', { name: AdirsVars.daRaw, type: SimVarValueType.Number }], + ['mach', { name: AdirsVars.mach, type: SimVarValueType.Number }], + ['latitude', { name: AdirsVars.latitude, type: SimVarValueType.Number }], + ['longitude', { name: AdirsVars.longitude, type: SimVarValueType.Number }], + ['irMaintWordRaw', { name: AdirsVars.irMaintWordRaw, type: SimVarValueType.Number }], +]); + +export interface SwitchingPanelVSimVars { + attHdgKnob: number; + airKnob: number; + dmcKnob: number; +} + +export enum SwitchingPanelVars { + attHdgKnob = 'L:A32NX_ATT_HDG_SWITCHING_KNOB', + airKnob = 'L:A32NX_AIR_DATA_SWITCHING_KNOB', + dmcKnob = 'L:A32NX_EIS_DMC_SWITCHING_KNOB', +} + +export const SwitchingPanelSimVarsDefinitions = new Map([ + ['attHdgKnob', { name: SwitchingPanelVars.attHdgKnob, type: SimVarValueType.Enum }], + ['airKnob', { name: SwitchingPanelVars.airKnob, type: SimVarValueType.Enum }], + ['dmcKnob', { name: SwitchingPanelVars.dmcKnob, type: SimVarValueType.Enum }], +]); diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UpdatableSimVarPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UpdatableSimVarPublisher.ts new file mode 100644 index 00000000000..0d4297738c7 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UpdatableSimVarPublisher.ts @@ -0,0 +1,13 @@ +import { SimVarDefinition, SimVarPublisher } from '@microsoft/msfs-sdk'; + +export class UpdatableSimVarPublisher extends SimVarPublisher { + /** + * Change the simvar read for a given key. + * @param key The key of the simvar in simVarMap + * @param value The new value to set the simvar to. + * @deprecated Removed upstream and won't be needed when DMC switching implemented properly + */ + public updateSimVarSource(key: keyof T & string, value: SimVarDefinition): void { + this.resolvedSimVars.set(key, value); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/common.scss b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/common.scss new file mode 100644 index 00000000000..590a984d975 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/common.scss @@ -0,0 +1,52 @@ +@import "definitions"; + +.SelfTest { + position: absolute; + left: 0%; + top: 0%; + width: 100%; + height: 100%; + border: none; +} + +.SelfTestBackground { + fill: $display-background; +} + +.SelfTestText { + font-size: 24px; + fill: $display-green; + visibility: visible !important; + + text-anchor: middle; + font-family: "Ecam", monospace; +} + +.MaintenanceMode { + position: absolute; + left: 0%; + top: 0%; + width: 100%; + height: 100%; + border: none; +} + +.EngineeringTestMode { + position: absolute; + left: 0%; + top: 0%; + width: 100%; + height: 100%; + border: none; + z-index: 999; + visibility: visible !important; + background-image: url('/Images/fbw-a32nx/Common/thalesTest.svg'); + background-size: cover; + font-family: "Ecam", monospace; +} + +.EngineeringTestModeText { + font-size: 21px; + color: black; + font-family: "Ecam", monospace; +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/definitions.scss b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/definitions.scss new file mode 100644 index 00000000000..f0b0de59ad0 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/definitions.scss @@ -0,0 +1,18 @@ +$font-size-small: 14px; +$font-size-medium: 16px; +$font-size-large: 17px; +$font-size-larger: 18px; +$font-size-xlarge: 20px; +$font-size-huge: 22px; +$font-size-title: 24px; + +$display-white: #ffffff; +$display-grey: #787878; +$display-amber: #e68000; +$display-cyan: #00ffff; +$display-green: #00ff00; +$display-magenta: #ff94ff; +$display-red: #ff0000; +$display-yellow: #ffff00; + +$display-background: #040404; diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.scss b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.scss new file mode 100644 index 00000000000..3ed49923bf1 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.scss @@ -0,0 +1,46 @@ +@import "./definitions.scss"; + +.GaugeComponent { + .Show { + display: block; + } + + .Hide { + display: none; + } + + .Gauge { + stroke: $display-white; + stroke-width: 2; + fill: none; + } + + .GaugeInactive { + stroke: $display-amber; + stroke-width: 2; + fill: none; + } + + .GaugeText { + stroke: $display-white; + font-size: 17px; + } + + .GaugeIndicator { + stroke: $display-green; + stroke-width: 3; + fill: none; + } + + .GaugeThrustLimitIndicator { + stroke: $display-amber; + stroke-width: 3; + fill: none; + } + + .GaugeThrustLimitIndicatorFill { + stroke: $display-amber; + stroke-width: 3; + fill: $display-amber; + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.tsx new file mode 100644 index 00000000000..2a9aab88ee2 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.tsx @@ -0,0 +1,392 @@ +import { DisplayComponent, FSComponent, Subscribable, Subject, VNode } from '@microsoft/msfs-sdk'; + +import './gauges.scss'; + +export const polarToCartesian = (centerX: number, centerY: number, radius: number, angleInDegrees: number) => { + const angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0; + + return { + x: centerX + (radius * Math.cos(angleInRadians)), + y: centerY + (radius * Math.sin(angleInRadians)), + }; +}; + +/** + * Draws an arc between startAngle and endAngle. This can start and finish anywhere on a circle + * Note all arcs are drawn in a clockwise fashion + * + * @param x x coordinate of arc centre + * @param y y coordinate of arc centre + * @param radius radius of arc + * @param startAngle value between 0 and 360 degrees where arc starts + * @param endAngle value between 0 and 360 degrees where arc finishes + */ +export const describeArc = (x: number, y: number, radius: number, startAngle: number, endAngle: number) => { + const start = polarToCartesian(x, y, radius, endAngle); + const end = polarToCartesian(x, y, radius, startAngle); + + const arcSize = startAngle > endAngle ? 360 - endAngle + startAngle : endAngle - startAngle; + const largeArcFlag = arcSize <= 180 ? '0' : '1'; + + return [ + 'M', start.x, start.y, + 'A', radius, radius, 0, largeArcFlag, 0, end.x, end.y, + ].join(' '); +}; + +export const valueRadianAngleConverter = (value: number, min: number, max: number, endAngle: number, startAngle: number, perpendicular: boolean = false) => { + const valuePercentage = (value - min) / (max - min); + const angle = perpendicular ? 0 : 90; + const angleInDegress = startAngle > endAngle + ? startAngle + (valuePercentage * (360 - startAngle + endAngle)) - angle + : startAngle + (valuePercentage * (endAngle - startAngle)) - angle; + const angleInRadians = angleInDegress * (Math.PI / 180.0); + return ({ + x: Math.cos(angleInRadians), + y: Math.sin(angleInRadians), + angle: angleInDegress, + }); +}; + +interface GaugeMarkerComponentProps { + value: Subscribable; + x: number; + y: number; + min: number; + max: number; + radius: number; + startAngle: Subscribable; + endAngle: Subscribable; + class: string | Subscribable; + textClass?: string; + useCentralAlignmentBaseline?: boolean; + showValue?: boolean; + indicator?: boolean; + outer?: boolean; + multiplierOuter?: number; + multiplierInner?: number; + textNudgeX?: number; + textNudgeY?: number; + halfIndicator?: boolean; + bold?: boolean; + roundLinecap?: boolean; +} +export class GaugeMarkerComponent extends DisplayComponent { + private startX = Subject.create(0); + + private startY = Subject.create(0); + + private endX = Subject.create(0); + + private endY = Subject.create(0); + + private textX = Subject.create(0); + + private textY = Subject.create(0); + + private text = Subject.create(''); + + private startAngle: number = 0; + + private endAngle: number = 0; + + private value: number = 0; + + constructor(props: GaugeMarkerComponentProps) { + super(props); + + this.props.textClass ??= 'GaugeText'; + this.props.multiplierOuter ??= 1.15; + this.props.multiplierInner ??= 0.85; + + this.startAngle = this.props.startAngle.get(); + this.endAngle = this.props.endAngle.get(); + this.value = this.props.value.get(); + this.update(); + } + + onAfterRender(node: VNode): void { + super.onAfterRender(node); + + this.props.startAngle.sub((a) => { + this.startAngle = a; + this.update(); + }); + + this.props.endAngle.sub((a) => { + this.endAngle = a; + this.update(); + }); + + this.props.value.sub((v) => { + this.value = v; + this.update(); + }); + } + + update(): void { + const dir = valueRadianAngleConverter(this.value, this.props.min, this.props.max, this.endAngle, this.startAngle); + + let start = { + x: this.props.x + (dir.x * this.props.radius * this.props.multiplierInner), + y: this.props.y + (dir.y * this.props.radius * this.props.multiplierInner), + }; + let end = { + x: this.props.x + (dir.x * this.props.radius), + y: this.props.y + (dir.y * this.props.radius), + }; + + if (this.props.outer) { + start = { + x: this.props.x + (dir.x * this.props.radius), + y: this.props.y + (dir.y * this.props.radius), + }; + end = { + x: this.props.x + (dir.x * this.props.radius * this.props.multiplierOuter), + y: this.props.y + (dir.y * this.props.radius * this.props.multiplierOuter), + }; + } + + if (this.props.indicator) { + // Need case for EGT and other gauges which do not originate from the centre of the arc + // In this case use original start definition + if (!this.props.halfIndicator) { + start = { x: this.props.x, y: this.props.y }; + } + + end = { + x: this.props.x + (dir.x * this.props.radius * this.props.multiplierOuter), + y: this.props.y + (dir.y * this.props.radius * this.props.multiplierOuter), + }; + } + + // Text + const pos = { + x: this.props.x + (dir.x * this.props.radius * this.props.multiplierInner) + this.props.textNudgeX, + y: this.props.y + (dir.y * this.props.radius * this.props.multiplierInner) + this.props.textNudgeY, + }; + + if (Number.isNaN(start.x)) { + console.log(dir); + console.log(this); + } + + this.startX.set(start.x); + this.startY.set(start.y); + this.endX.set(end.x); + this.endY.set(end.y); + this.textX.set(pos.x); + this.textY.set(pos.y); + this.text.set(this.props.showValue ? Math.abs(this.value).toString() : ''); + } + + render(): VNode { + return ( + <> + + + {this.text} + + + ); + } +} + +interface GaugeMaxComponentProps { + value: Subscribable; + x: number; + y: number; + min: number; + max: number; + radius: number; + startAngle: Subscribable; + endAngle: Subscribable; + class: string; +} +export class GaugeMaxComponent extends DisplayComponent { + private rectX = Subject.create(0); + + private rectY = Subject.create(0); + + private transform = Subject.create(''); + + private startAngle: number = 0; + + private endAngle: number = 0; + + private value: number = 0; + + constructor(props: GaugeMaxComponentProps) { + super(props); + + this.startAngle = this.props.startAngle.get(); + this.endAngle = this.props.endAngle.get(); + this.value = this.props.value.get(); + this.update(); + } + + onAfterRender(node: VNode): void { + super.onAfterRender(node); + + this.props.startAngle.sub((a) => { + this.startAngle = a; + this.update(); + }); + + this.props.endAngle.sub((a) => { + this.endAngle = a; + this.update(); + }); + + this.props.value.sub((v) => { + this.value = v; + this.update(); + }); + } + + update(): void { + const dir = valueRadianAngleConverter(this.value, this.props.min, this.props.max, this.endAngle, this.startAngle); + + const xy = { x: this.props.x + (dir.x * this.props.radius), y: this.props.y + (dir.y * this.props.radius) }; + + this.rectX.set(xy.x); + this.rectY.set(xy.y); + this.transform.set(`rotate(${dir.angle} ${xy.x} ${xy.y})`); + } + + render(): VNode { + return ( + + ); + } +} + +interface ThrottlePositionDonutComponentProps { + value: Subscribable; + x: number; + y: number; + min: number; + max: number; + radius: number; + startAngle: Subscribable; + endAngle: Subscribable; + class: string; +} +export class ThrottlePositionDonutComponent extends DisplayComponent { + private circleX = Subject.create(0); + + private circleY = Subject.create(0); + + private startAngle: number = 0; + + private endAngle: number = 0; + + private value: number = 0; + + constructor(props: ThrottlePositionDonutComponentProps) { + super(props); + + this.startAngle = this.props.startAngle.get(); + this.endAngle = this.props.endAngle.get(); + this.value = this.props.value.get(); + this.update(); + } + + onAfterRender(node: VNode): void { + super.onAfterRender(node); + + this.props.startAngle.sub((a) => { + this.startAngle = a; + this.update(); + }); + + this.props.endAngle.sub((a) => { + this.endAngle = a; + this.update(); + }); + + this.props.value.sub((v) => { + this.value = v; + this.update(); + }); + } + + update(): void { + const dir = valueRadianAngleConverter(this.value, this.props.min, this.props.max, this.endAngle, this.startAngle); + + this.circleX.set(dir.x * this.props.radius * 1.12); + this.circleY.set(dir.y * this.props.radius * 1.12); + } + + render(): VNode { + return ( + + ); + } +} + +interface GaugeComponentProps { + x: number; + y: number; + radius: number; + startAngle: Subscribable; + endAngle: Subscribable; + class: string; + visible?: Subscribable; +} +export class GaugeComponent extends DisplayComponent { + private arc = Subject.create(''); + + private startAngle: number = 0; + + private endAngle: number = 0; + + constructor(props: GaugeComponentProps) { + super(props); + + this.startAngle = this.props.startAngle.get(); + this.endAngle = this.props.endAngle.get(); + this.updateArc(); + } + + onAfterRender(node: VNode): void { + super.onAfterRender(node); + + this.props.startAngle.sub((a) => { + this.startAngle = a; + this.updateArc(); + }); + + this.props.endAngle.sub((a) => { + this.endAngle = a; + this.updateArc(); + }); + } + + updateArc(): void { + this.arc.set(describeArc(this.props.x, this.props.y, this.props.radius, this.startAngle, this.endAngle)); + } + + render(): VNode { + return ( + (v ? 'inherit' : 'hidden')) ?? 'inherit'}> + + {this.props.children} + + ); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx new file mode 100644 index 00000000000..ac25ee2862c --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/DmcPublisher.tsx @@ -0,0 +1,83 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarDefinition, SimVarPublisher, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; +import { Arinc429WordData, Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; +import { AdirsSimVars } from '../SimVarTypes'; + +export interface DmcLogicEvents { + trueRefActive: boolean, + heading: Arinc429WordData, + track: Arinc429WordData, +} + +export interface DmcDiscreteInputEvents { + trueRefPushButton: boolean, +} + +export type DmcEvents = DmcLogicEvents & DmcDiscreteInputEvents; + +export class DmcPublisher extends SimVarPublisher { + private readonly irMaintWord = Arinc429RegisterSubject.createEmpty(); + + private readonly magHeading = Arinc429RegisterSubject.createEmpty(); + + private readonly trueHeading = Arinc429RegisterSubject.createEmpty(); + + private readonly magTrack = Arinc429RegisterSubject.createEmpty(); + + private readonly trueTrack = Arinc429RegisterSubject.createEmpty(); + + private readonly trueRefPb = Subject.create(false); + + private readonly trueRefActive = Subject.create(false); + + constructor(private eventBus: EventBus) { + const simVars = new Map([ + // FIXME, per-side + ['trueRefPushButton', { name: 'L:A32NX_PUSH_TRUE_REF', type: SimVarValueType.Bool }], + ]); + super(simVars, eventBus); + } + + init(): void { + const pub = this.eventBus.getPublisher(); + + this.trueRefActive.sub((v) => { + pub.pub('trueRefActive', v); + this.handleHeading(); + }, true); + + const sub = this.eventBus.getSubscriber(); + + this.irMaintWord.sub(this.handleTrueRef.bind(this)); + this.trueRefPb.sub(this.handleTrueRef.bind(this), true); + + this.magHeading.sub(this.handleHeading.bind(this)); + this.magTrack.sub(this.handleHeading.bind(this)); + this.trueHeading.sub(this.handleHeading.bind(this)); + this.trueTrack.sub(this.handleHeading.bind(this)); + + sub.on('irMaintWordRaw').handle((v) => this.irMaintWord.setWord(v)); + sub.on('trueRefPushButton').whenChanged().handle((v) => this.trueRefPb.set(v)); + sub.on('magHeadingRaw').handle((v) => this.magHeading.setWord(v)); + sub.on('magTrackRaw').handle((v) => this.magTrack.setWord(v)); + sub.on('trueHeadingRaw').handle((v) => this.trueHeading.setWord(v)); + sub.on('trueTrackRaw').handle((v) => this.trueTrack.setWord(v)); + } + + private handleTrueRef(): void { + // true ref is active when the PB is pressed or the ADIRU is at an extreme latitude + // and the ADIRU must not be in ATT reversion mode + const trueRequested = this.irMaintWord.get().bitValueOr(15, false) || this.trueRefPb.get(); + this.trueRefActive.set(trueRequested && !this.irMaintWord.get().bitValueOr(2, false)); + } + + private handleHeading(): void { + const pub = this.eventBus.getPublisher(); + + pub.pub('heading', this.trueRefActive.get() ? this.trueHeading.get() : this.magHeading.get()); + pub.pub('track', this.trueRefActive.get() ? this.trueTrack.get() : this.magTrack.get()); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts new file mode 100644 index 00000000000..58be7046ada --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/EgpwcBusPublisher.ts @@ -0,0 +1,30 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; +import { EfisSide } from '@flybywiresim/fbw-sdk'; + +export enum TerrainLevelMode { + PeaksMode = 0, + Warning = 1, + Caution = 2, +} + +export interface EgpwcSimVars { + 'egpwc.minElevation': number, + 'egpwc.minElevationMode': TerrainLevelMode, + 'egpwc.maxElevation': number, + 'egpwc.maxElevationMode': TerrainLevelMode, +} + +export class EgpwcBusPublisher extends SimVarPublisher { + constructor(bus: EventBus, side: EfisSide) { + super(new Map([ + ['egpwc.minElevation', { name: `L:A32NX_EGPWC_ND_${side}_TERRAIN_MIN_ELEVATION`, type: SimVarValueType.Number }], + ['egpwc.minElevationMode', { name: `L:A32NX_EGPWC_ND_${side}_TERRAIN_MIN_ELEVATION_MODE`, type: SimVarValueType.Number }], + ['egpwc.maxElevation', { name: `L:A32NX_EGPWC_ND_${side}_TERRAIN_MAX_ELEVATION`, type: SimVarValueType.Number }], + ['egpwc.maxElevationMode', { name: `L:A32NX_EGPWC_ND_${side}_TERRAIN_MAX_ELEVATION_MODE`, type: SimVarValueType.Number }], + ]), bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FGDataPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FGDataPublisher.ts new file mode 100644 index 00000000000..2ea220ff2dc --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FGDataPublisher.ts @@ -0,0 +1,16 @@ +import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; +import { LateralMode } from '@shared/autopilot'; + +export interface FGVars { + 'fg.fma.lateralMode': LateralMode, + 'fg.fma.lateralArmedBitmask': number, +} + +export class FGDataPublisher extends SimVarPublisher { + constructor(bus: EventBus) { + super(new Map([ + ['fg.fma.lateralMode', { name: 'L:A32NX_FMA_LATERAL_MODE', type: SimVarValueType.Number }], + ['fg.fma.lateralArmedBitmask', { name: 'L:A32NX_FMA_LATERAL_ARMED', type: SimVarValueType.Number }], + ]), bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FMBusPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FMBusPublisher.ts new file mode 100644 index 00000000000..13b43dd3fbb --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FMBusPublisher.ts @@ -0,0 +1,22 @@ +import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; + +export interface FMBusEvents { + 'fm.1.healthy_discrete': boolean, + + 'fm.2.healthy_discrete': boolean, + + 'fm.1.tuning_discrete_word': number, + + 'fm.2.tuning_discrete_word': number, +} + +export class FMBusPublisher extends SimVarPublisher { + constructor(bus: EventBus) { + super(new Map([ + ['fm.1.healthy_discrete', { name: 'L:A32NX_FM1_HEALTHY_DISCRETE', type: SimVarValueType.Bool }], + ['fm.2.healthy_discrete', { name: 'L:A32NX_FM2_HEALTHY_DISCRETE', type: SimVarValueType.Bool }], + ['fm.1.tuning_discrete_word', { name: 'L:A32NX_FM1_NAV_DISCRETE', type: SimVarValueType.Number }], + ['fm.2.tuning_discrete_word', { name: 'L:A32NX_FM2_NAV_DISCRETE', type: SimVarValueType.Number }], + ]), bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts new file mode 100644 index 00000000000..29f9678db84 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher.ts @@ -0,0 +1,29 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; +import { EfisNdMode, EfisOption, EfisSide, NavAidMode } from '@flybywiresim/fbw-sdk'; + +export interface FcuSimVars { + ndRangeSetting: number, + ndMode: EfisNdMode, + option: EfisOption, + navaidMode1: NavAidMode, + navaidMode2: NavAidMode, + /** State of the LS pushbutton on the EFIS control panel. */ + efisLsActive: boolean, +} + +export class FcuBusPublisher extends SimVarPublisher { + constructor(bus: EventBus, efisSide: EfisSide) { + super(new Map([ + ['ndRangeSetting', { name: `L:A32NX_EFIS_${efisSide}_ND_RANGE`, type: SimVarValueType.Enum }], + ['ndMode', { name: `L:A32NX_EFIS_${efisSide}_ND_MODE`, type: SimVarValueType.Enum }], + ['option', { name: `L:A32NX_EFIS_${efisSide}_OPTION`, type: SimVarValueType.Enum }], + ['navaidMode1', { name: `L:A32NX_EFIS_${efisSide}_NAVAID_1_MODE`, type: SimVarValueType.Enum }], + ['navaidMode2', { name: `L:A32NX_EFIS_${efisSide}_NAVAID_2_MODE`, type: SimVarValueType.Enum }], + ['efisLsActive', { name: `L:BTN_LS_${efisSide === 'L' ? 1 : 2}_FILTER_ACTIVE`, type: SimVarValueType.Bool }], + ]), bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher.ts new file mode 100644 index 00000000000..b5f1d36ea07 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher.ts @@ -0,0 +1,50 @@ +import { EventBus, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; +import { SwitchableSimVarProvider } from './SwitchableProvider'; + +export interface FmsVars { + ndMessageFlags: number, + crossTrackError: number, + linearDeviationActive: boolean; + targetAltitude: number; + verticalProfileLatched: boolean; + showSpeedMargins: boolean; + upperSpeedMargin: number; + lowerSpeedMargin: number; + rnp: number; + toWptIdent0: number; + toWptIdent1: number; + toWptBearing: number; + toWptTrueBearing: number; + toWptDistance: number; + toWptEta: number; + apprMessage0: number; + apprMessage1: number; +} + +export class FmsDataPublisher extends SwitchableSimVarProvider { + constructor( + bus: EventBus, + stateSubject: Subject<'L' | 'R'>, + ) { + super(new Map([ + ['ndMessageFlags', { name: (side) => `L:A32NX_EFIS_${side}_ND_FM_MESSAGE_FLAGS`, type: SimVarValueType.Number }], + ['crossTrackError', { name: (_side) => 'L:A32NX_FG_CROSS_TRACK_ERROR', type: SimVarValueType.NM }], + ['linearDeviationActive', { name: (_side) => 'L:A32NX_PFD_LINEAR_DEVIATION_ACTIVE', type: SimVarValueType.Bool }], + ['targetAltitude', { name: (_side) => 'L:A32NX_PFD_TARGET_ALTITUDE', type: SimVarValueType.Feet }], + ['verticalProfileLatched', { name: (_side) => 'L:A32NX_PFD_VERTICAL_PROFILE_LATCHED', type: SimVarValueType.Bool }], + ['showSpeedMargins', { name: (_side) => 'L:A32NX_PFD_SHOW_SPEED_MARGINS', type: SimVarValueType.Bool }], + ['upperSpeedMargin', { name: (_side) => 'L:A32NX_PFD_UPPER_SPEED_MARGIN', type: SimVarValueType.Knots }], + ['lowerSpeedMargin', { name: (_side) => 'L:A32NX_PFD_LOWER_SPEED_MARGIN', type: SimVarValueType.Knots }], + ['rnp', { name: (side) => `L:A32NX_FMGC_${side}_RNP`, type: SimVarValueType.Number }], + ['toWptIdent0', { name: (side) => `L:A32NX_EFIS_${side}_TO_WPT_IDENT_0`, type: SimVarValueType.Number }], + ['toWptIdent1', { name: (side) => `L:A32NX_EFIS_${side}_TO_WPT_IDENT_1`, type: SimVarValueType.Number }], + ['toWptBearing', { name: (side) => `L:A32NX_EFIS_${side}_TO_WPT_BEARING`, type: SimVarValueType.Degree }], + ['toWptTrueBearing', { name: (side) => `L:A32NX_EFIS_${side}_TO_WPT_TRUE_BEARING`, type: SimVarValueType.Degree }], + ['toWptDistance', { name: (side) => `L:A32NX_EFIS_${side}_TO_WPT_DISTANCE`, type: SimVarValueType.Number }], + ['toWptEta', { name: (side) => `L:A32NX_EFIS_${side}_TO_WPT_ETA`, type: SimVarValueType.Seconds }], + ['apprMessage0', { name: (side) => `L:A32NX_EFIS_${side}_APPR_MSG_0`, type: SimVarValueType.Number }], + ['apprMessage1', { name: (side) => `L:A32NX_EFIS_${side}_APPR_MSG_1`, type: SimVarValueType.Number }], + + ]), stateSubject, bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher.ts new file mode 100644 index 00000000000..45029ce72a0 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/FuelSystemPublisher.ts @@ -0,0 +1,53 @@ +import { EventBus, IndexedEventType, PublishPacer, SimVarPublisher, SimVarPublisherEntry, SimVarValueType } from '@microsoft/msfs-sdk'; + +/* eslint-disable camelcase */ +export interface BaseFuelSystemEvents { + fuel_ctr_tk_mode_sel_man: boolean, + /** The valve's switch: */ + fuel_valve_switch: boolean; + /** The valve's actual continous position, in percent, 0 ... 1 */ + fuel_valve_open: number; + /** The pump's switch state */ + fuel_pump_switch: boolean; + /** The pump's active state (ex. false when pump is on but no fuel in tank) */ + fuel_pump_active: boolean; + /** The engines's fuel pressure in psi. */ + fuel_engine_pressure: number; + /** The pressure of a fuel line in psi. */ + fuel_line_pressure: number; + /** The fuel flow of a fuel line in gallons per hour. */ + fuel_line_flow: number; + /** The quantity of fuel in the selected tank (by tank index), in gallons. */ + fuel_tank_quantity: number; +} + +type IndexedTopics = 'fuel_valve_switch' | 'fuel_valve_open' | 'fuel_pump_switch' | 'fuel_pump_active' + | 'fuel_engine_pressure' | 'fuel_line_pressure' | 'fuel_line_flow' | 'fuel_tank_quantity'; + +type FuelSystemIndexedEvents = { + [P in keyof Pick as IndexedEventType

]: BaseFuelSystemEvents[P]; +}; + +/** + * Fuel System events. + */ +export interface FuelSystemEvents extends BaseFuelSystemEvents, FuelSystemIndexedEvents { +} + +export class FuelSystemPublisher extends SimVarPublisher { + constructor(bus: EventBus, pacer?: PublishPacer) { + const simvars: [keyof FuelSystemEvents, SimVarPublisherEntry][] = [ + ['fuel_ctr_tk_mode_sel_man', { name: 'L:A32NX_OVHD_FUEL_MODESEL_MANUAL', type: SimVarValueType.Number, map: (v) => !!v }], + ['fuel_valve_switch', { name: 'FUELSYSTEM VALVE SWITCH:#index#', type: SimVarValueType.Bool, indexed: true, map: (v) => !!v }], + ['fuel_valve_open', { name: 'FUELSYSTEM VALVE OPEN:#index#', type: SimVarValueType.Number, indexed: true }], + ['fuel_pump_switch', { name: 'FUELSYSTEM PUMP SWITCH:#index#', type: SimVarValueType.Bool, indexed: true, map: (v) => !!v }], + ['fuel_pump_active', { name: 'FUELSYSTEM PUMP ACTIVE:#index#', type: SimVarValueType.Bool, indexed: true, map: (v) => !!v }], + ['fuel_engine_pressure', { name: 'FUELSYSTEM ENGINE PRESSURE:#index#', type: SimVarValueType.PSI, indexed: true }], + ['fuel_line_pressure', { name: 'FUELSYSTEM LINE FUEL PRESSURE:#index#', type: SimVarValueType.PSI, indexed: true }], + ['fuel_line_flow', { name: 'FUELSYSTEM LINE FUEL FLOW:#index#', type: SimVarValueType.GPH, indexed: true }], + ['fuel_tank_quantity', { name: 'FUELSYSTEM TANK QUANTITY:#index#', type: SimVarValueType.GAL, indexed: true }], + ]; + + super(new Map(simvars), bus, pacer); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/SwitchableProvider.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/SwitchableProvider.ts new file mode 100644 index 00000000000..6dd8c1308b9 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/SwitchableProvider.ts @@ -0,0 +1,31 @@ +import { EventBus, SimVarValueType, Subject } from '@microsoft/msfs-sdk'; +import { UpdatableSimVarPublisher } from '../UpdatableSimVarPublisher'; + +export interface SwitchableSimVarDefinition { + name: (state: TState) => string; + + type: SimVarValueType; +} + +export abstract class SwitchableSimVarProvider extends UpdatableSimVarPublisher { + protected constructor( + private simVars: Map>, + public stateSubject: Subject, + bus: EventBus, + ) { + super(new Map(Array.from(simVars.entries()).map(([k, v]) => [k, { + name: v.name(stateSubject.get()), + type: v.type, + }])), bus); + + stateSubject.sub((value) => this.updateDefinitions(value)); + } + + private updateDefinitions(newStateValue: TState) { + for (const [key, value] of this.simVars) { + const newName = value.name(newStateValue); + + this.updateSimVarSource(key, { name: newName, type: value.type }); + } + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/TcasBusPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/TcasBusPublisher.ts new file mode 100644 index 00000000000..dc7882bb0c4 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/TcasBusPublisher.ts @@ -0,0 +1,17 @@ +import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; + +export interface TcasSimVars { + tcasTaOnly: boolean, + tcasFault: boolean, + tcasMode: number, +} + +export class TcasBusPublisher extends SimVarPublisher { + constructor(bus: EventBus) { + super(new Map([ + ['tcasTaOnly', { name: 'L:A32NX_TCAS_TA_ONLY', type: SimVarValueType.Bool }], + ['tcasFault', { name: 'L:A32NX_TCAS_FAULT', type: SimVarValueType.Bool }], + ['tcasMode', { name: 'L:A32NX_TCAS_MODE', type: SimVarValueType.Number }], + ]), bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/VorBusPublisher.ts b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/VorBusPublisher.ts new file mode 100644 index 00000000000..a4253e9c1eb --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/providers/VorBusPublisher.ts @@ -0,0 +1,134 @@ +import { EventBus, SimVarPublisher, SimVarValueType } from '@microsoft/msfs-sdk'; + +export interface VorSimVars { + nav1Ident: string, + nav1Frequency: number, + nav1HasDme: boolean, + nav1DmeDistance: NauticalMiles, + nav1RelativeBearing: Degrees, + nav1Obs: Degrees, + nav1Localizer: Degrees, + nav1RadialError: Degrees, + nav1Available: boolean, + nav1StationDeclination: Degrees, + nav1Location: LatLongAlt, + + nav2Ident: string, + nav2Frequency: number, + nav2HasDme: boolean, + nav2DmeDistance: NauticalMiles, + nav2RelativeBearing: Degrees, + nav2Obs: Degrees, + nav2Localizer: Degrees, + nav2RadialError: Degrees, + nav2Available: boolean, + nav2StationDeclination: Degrees, + nav2Location: LatLongAlt, + + nav3Ident: string, + nav3Frequency: number, + nav3HasDme: boolean, + nav3DmeDistance: NauticalMiles, + nav3RelativeBearing: Degrees, + nav3Obs: Degrees, + nav3Localizer: Degrees, + nav3RadialError: Degrees, + nav3Available: boolean, + nav3StationDeclination: Degrees, + nav3Location: LatLongAlt, + + nav4Ident: string, + nav4Frequency: number, + nav4HasDme: boolean, + nav4DmeDistance: NauticalMiles, + nav4RelativeBearing: Degrees, + nav4Obs: Degrees, + nav4Localizer: Degrees, + nav4RadialError: Degrees, + nav4Available: boolean, + nav4StationDeclination: Degrees, + nav4Location: LatLongAlt, + + localizerValid: boolean, + glideSlopeValid: boolean, + glideSlopeDeviation: number, + + adf1Ident: string, + adf1ActiveFrequency: number, + adf1SignalStrength: number, + adf1Radial: number + + adf2Ident: string, + adf2ActiveFrequency: number, + adf2SignalStrength: number, + adf2Radial: number, +} + +export class VorBusPublisher extends SimVarPublisher { + constructor(bus: EventBus) { + super(new Map([ + ['nav1Ident', { name: 'NAV IDENT:1', type: SimVarValueType.String }], + ['nav1Frequency', { name: 'NAV ACTIVE FREQUENCY:1', type: SimVarValueType.MHz }], + ['nav1HasDme', { name: 'NAV HAS DME:1', type: SimVarValueType.Bool }], + ['nav1DmeDistance', { name: 'NAV DME:1', type: SimVarValueType.NM }], + ['nav1RelativeBearing', { name: 'NAV RELATIVE BEARING TO STATION:1', type: SimVarValueType.Degree }], + ['nav1Obs', { name: 'NAV OBS:1', type: SimVarValueType.Degree }], + ['nav1Localizer', { name: 'NAV LOCALIZER:1', type: SimVarValueType.Degree }], + ['nav1RadialError', { name: 'NAV RADIAL ERROR:1', type: SimVarValueType.Degree }], + // This is fine at the moment. The database does not have the necessary information to implement proper logic. + ['nav1Available', { name: 'NAV HAS NAV:1', type: SimVarValueType.Bool }], + ['nav1StationDeclination', { name: 'NAV MAGVAR:1', type: SimVarValueType.Degree }], + ['nav1Location', { name: 'NAV VOR LATLONALT:1', type: SimVarValueType.LLA }], + + ['nav2Ident', { name: 'NAV IDENT:2', type: SimVarValueType.String }], + ['nav2Frequency', { name: 'NAV ACTIVE FREQUENCY:2', type: SimVarValueType.MHz }], + ['nav2HasDme', { name: 'NAV HAS DME:2', type: SimVarValueType.Bool }], + ['nav2DmeDistance', { name: 'NAV DME:2', type: SimVarValueType.NM }], + ['nav2RelativeBearing', { name: 'NAV RELATIVE BEARING TO STATION:2', type: SimVarValueType.Degree }], + ['nav2Obs', { name: 'NAV OBS:2', type: SimVarValueType.Degree }], + ['nav2Localizer', { name: 'NAV LOCALIZER:2', type: SimVarValueType.Degree }], + ['nav2RadialError', { name: 'NAV RADIAL ERROR:2', type: SimVarValueType.Degree }], + ['nav2Available', { name: 'NAV HAS NAV:2', type: SimVarValueType.Bool }], + ['nav2StationDeclination', { name: 'NAV MAGVAR:2', type: SimVarValueType.Degree }], + ['nav2Location', { name: 'NAV VOR LATLONALT:2', type: SimVarValueType.LLA }], + + ['nav3Ident', { name: 'NAV IDENT:3', type: SimVarValueType.String }], + ['nav3Frequency', { name: 'NAV ACTIVE FREQUENCY:3', type: SimVarValueType.MHz }], + ['nav3HasDme', { name: 'NAV HAS DME:3', type: SimVarValueType.Bool }], + ['nav3DmeDistance', { name: 'NAV DME:3', type: SimVarValueType.NM }], + ['nav3RelativeBearing', { name: 'NAV RELATIVE BEARING TO STATION:3', type: SimVarValueType.Degree }], + ['nav3Obs', { name: 'NAV OBS:3', type: SimVarValueType.Degree }], + ['nav3Localizer', { name: 'NAV LOCALIZER:3', type: SimVarValueType.Degree }], + ['nav3RadialError', { name: 'NAV RADIAL ERROR:3', type: SimVarValueType.Degree }], + ['nav3Available', { name: 'NAV HAS NAV:3', type: SimVarValueType.Bool }], + ['nav3StationDeclination', { name: 'NAV MAGVAR:3', type: SimVarValueType.Degree }], + ['nav3Location', { name: 'NAV VOR LATLONALT:3', type: SimVarValueType.LLA }], + + ['nav4Ident', { name: 'NAV IDENT:4', type: SimVarValueType.String }], + ['nav4Frequency', { name: 'NAV ACTIVE FREQUENCY:4', type: SimVarValueType.MHz }], + ['nav4HasDme', { name: 'NAV HAS DME:4', type: SimVarValueType.Bool }], + ['nav4DmeDistance', { name: 'NAV DME:4', type: SimVarValueType.NM }], + ['nav4RelativeBearing', { name: 'NAV RELATIVE BEARING TO STATION:4', type: SimVarValueType.Degree }], + ['nav4Obs', { name: 'NAV OBS:4', type: SimVarValueType.Degree }], + ['nav4Localizer', { name: 'NAV LOCALIZER:4', type: SimVarValueType.Degree }], + ['nav4RadialError', { name: 'NAV RADIAL ERROR:4', type: SimVarValueType.Degree }], + ['nav4Available', { name: 'NAV HAS NAV:4', type: SimVarValueType.Bool }], + ['nav4StationDeclination', { name: 'NAV MAGVAR:4', type: SimVarValueType.Degree }], + ['nav4Location', { name: 'NAV VOR LATLONALT:4', type: SimVarValueType.LLA }], + + ['localizerValid', { name: 'L:A32NX_RADIO_RECEIVER_LOC_IS_VALID', type: SimVarValueType.Bool }], + ['glideSlopeValid', { name: 'L:A32NX_RADIO_RECEIVER_GS_IS_VALID', type: SimVarValueType.Bool }], + ['glideSlopeDeviation', { name: 'L:A32NX_RADIO_RECEIVER_GS_DEVIATION', type: SimVarValueType.Number }], + + ['adf1Ident', { name: 'ADF IDENT:1', type: SimVarValueType.String }], + ['adf1ActiveFrequency', { name: 'ADF ACTIVE FREQUENCY:1', type: SimVarValueType.KHz }], + ['adf1SignalStrength', { name: 'ADF SIGNAL:1', type: SimVarValueType.Number }], + ['adf1Radial', { name: 'ADF RADIAL:1', type: SimVarValueType.Degree }], + + ['adf2Ident', { name: 'ADF IDENT:2', type: SimVarValueType.String }], + ['adf2ActiveFrequency', { name: 'ADF ACTIVE FREQUENCY:2', type: SimVarValueType.KHz }], + ['adf2SignalStrength', { name: 'ADF SIGNAL:2', type: SimVarValueType.Number }], + ['adf2Radial', { name: 'ADF RADIAL:2', type: SimVarValueType.Degree }], + ]), bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/tsconfig.json b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/tsconfig.json new file mode 100644 index 00000000000..efc24f00dc4 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../tsconfig.json", + + "compilerOptions": { + "incremental": false /* Enables incremental builds */, + "target": "es2017" /* Specifies the ES2017 target, compatible with Coherent GT */, + "module": "es2015" /* Ensures that modules are at least es2015 */, + "strict": false /* Enables strict type checking, highly recommended but optional */, + "esModuleInterop": true /* Emits additional JS to work with CommonJS modules */, + "skipLibCheck": true /* Skip type checking on library .d.ts files */, + "forceConsistentCasingInFileNames": true /* Ensures correct import casing */, + "moduleResolution": "node" /* Enables compatibility with MSFS SDK bare global imports */, + "jsxFactory": "FSComponent.buildComponent" /* Required for FSComponent framework JSX */, + "jsxFragmentFactory": "FSComponent.Fragment" /* Required for FSComponent framework JSX */, + "jsx": "react" /* Required for FSComponent framework JSX */ + } +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/.eslintrc.js b/fbw-a380x/src/systems/instruments/src/ND/.eslintrc.js new file mode 100644 index 00000000000..c4d8630eebe --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/.eslintrc.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = { + + extends: '../../../../.eslintrc.js', + + // overrides airbnb, use sparingly + rules: { 'react/no-unknown-property': 'off', 'react/style-prop-object': 'off', 'arrow-body-style': 'off', 'camelcase': 'off' }, + +}; diff --git a/fbw-a380x/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts b/fbw-a380x/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts new file mode 100644 index 00000000000..8820b61c138 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts @@ -0,0 +1,44 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { BasePublisher, EventBus } from '@microsoft/msfs-sdk'; +import { EfisSide, NdSymbol, NdTraffic } from '@flybywiresim/fbw-sdk'; +import { PathVector } from '@fmgc/guidance/lnav/PathVector'; +import { GenericDataListenerSync } from '@flybywiresim/fbw-sdk'; + +export interface FmsSymbolsData { + symbols: NdSymbol[], + vectorsActive: PathVector[], + vectorsDashed: PathVector[], + vectorsTemporary: PathVector[], + traffic: NdTraffic[], +} + +export class FmsSymbolsPublisher extends BasePublisher { + private readonly events: GenericDataListenerSync[] = []; + + constructor(bus: EventBus, side: EfisSide) { + super(bus); + + this.events.push(new GenericDataListenerSync((ev, data) => { + this.publish('symbols', data); + }, `A32NX_EFIS_${side}_SYMBOLS`)); + + this.events.push(new GenericDataListenerSync((ev, data: PathVector[]) => { + this.publish('vectorsActive', data); + }, `A32NX_EFIS_VECTORS_${side}_ACTIVE`)); + + this.events.push(new GenericDataListenerSync((ev, data: PathVector[]) => { + this.publish('vectorsDashed', data); + }, `A32NX_EFIS_VECTORS_${side}_DASHED`)); + + this.events.push(new GenericDataListenerSync((ev, data: PathVector[]) => { + this.publish('vectorsTemporary', data); + }, `A32NX_EFIS_VECTORS_${side}_TEMPORARY`)); + + this.events.push(new GenericDataListenerSync((ev, data: NdTraffic[]) => { + this.publish('traffic', data); + }, 'A32NX_TCAS_TRAFFIC')); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/NDControlEvents.ts b/fbw-a380x/src/systems/instruments/src/ND/NDControlEvents.ts new file mode 100644 index 00000000000..f35c8bd11ee --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/NDControlEvents.ts @@ -0,0 +1,80 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +/** + * Events for internal ND communication between components + */ +import { EfisNdMode } from '@flybywiresim/fbw-sdk'; + +export interface NDControlEvents { + /** + * Set if the plane icon is visible + */ + set_show_plane: boolean, + + /** + * Set the X position of the plane icon (0 to 786) + */ + set_plane_x: number, + + /** + * Set the Y position of the plane icon (0 to 786) + */ + set_plane_y: number, + + /** + * Set the rotation of the plane icon (degrees) + */ + set_plane_rotation: number, + + /** + * Set if the map is visible + */ + set_show_map: boolean, + + /** + * Set if the map is recomputing (RANGE CHANGE, MODE CHANGE) + */ + set_map_recomputing: boolean, + + /** + * Set the center latitude of the map + */ + set_map_center_lat: number, + + /** + * Set the center longitude of the map + */ + set_map_center_lon: number, + + /** + * Set the center Y-axis bias of the map + */ + set_map_center_y_bias: number, + + /** + * Set the true course up of the map + */ + set_map_up_course: number, + + /** + * Set the pixel radius of the map + */ + set_map_pixel_radius: number, + + /** + * Set the range radius of the map + */ + set_map_range_radius: number, + + /** + * Set the EFIS ND mode of the map + */ + set_map_efis_mode: EfisNdMode, + + /** + * Event for the CHRONO button being pushed + */ + chrono_pushed: void, +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/NDSimvarPublisher.tsx b/fbw-a380x/src/systems/instruments/src/ND/NDSimvarPublisher.tsx new file mode 100644 index 00000000000..92757a90f88 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/NDSimvarPublisher.tsx @@ -0,0 +1,59 @@ +import { EventBus, SimVarDefinition, SimVarValueType } from '@microsoft/msfs-sdk'; +import { + AdirsSimVarDefinitions, + AdirsSimVars, + SwitchingPanelSimVarsDefinitions, + SwitchingPanelVSimVars, +} from '../MsfsAvionicsCommon/SimVarTypes'; +import { UpdatableSimVarPublisher } from '../MsfsAvionicsCommon/UpdatableSimVarPublisher'; + +export type NDSimvars = AdirsSimVars & SwitchingPanelVSimVars & { + elec: boolean; + elecFo: boolean; + potentiometerCaptain: number; + potentiometerFo: number; + ilsCourse: number; + selectedWaypointLat: Degrees; + selectedWaypointLong: Degrees; + selectedHeading: Degrees; + pposLat: Degrees; + pposLong: Degrees; + absoluteTime: Seconds; + } + +export enum NDVars { + elec = 'L:A32NX_ELEC_AC_ESS_BUS_IS_POWERED', + elecFo = 'L:A32NX_ELEC_AC_2_BUS_IS_POWERED', + potentiometerCaptain = 'LIGHT POTENTIOMETER:89', + potentiometerFo = 'LIGHT POTENTIOMETER:91', + ilsCourse = 'L:A32NX_FM_LS_COURSE', + selectedWaypointLat = 'L:A32NX_SELECTED_WAYPOINT_LAT', + selectedWaypointLong = 'L:A32NX_SELECTED_WAYPOINT_LONG', + selectedHeading = 'L:A32NX_FCU_HEADING_SELECTED', + pposLat = 'PLANE LATITUDE', // TODO replace with fm position + pposLong = 'PLANE LONGITUDE', // TODO replace with fm position + absoluteTime = 'E:ABSOLUTE TIME', +} + +/** A publisher to poll and publish nav/com simvars. */ +export class NDSimvarPublisher extends UpdatableSimVarPublisher { + private static simvars = new Map([ + ...AdirsSimVarDefinitions, + ...SwitchingPanelSimVarsDefinitions, + ['elec', { name: NDVars.elec, type: SimVarValueType.Bool }], + ['elecFo', { name: NDVars.elecFo, type: SimVarValueType.Bool }], + ['potentiometerCaptain', { name: NDVars.potentiometerCaptain, type: SimVarValueType.Number }], + ['potentiometerFo', { name: NDVars.potentiometerFo, type: SimVarValueType.Number }], + ['ilsCourse', { name: NDVars.ilsCourse, type: SimVarValueType.Number }], + ['selectedWaypointLat', { name: NDVars.selectedWaypointLat, type: SimVarValueType.Degree }], + ['selectedWaypointLong', { name: NDVars.selectedWaypointLong, type: SimVarValueType.Degree }], + ['selectedHeading', { name: NDVars.selectedHeading, type: SimVarValueType.Degree }], + ['pposLat', { name: NDVars.pposLat, type: SimVarValueType.Degree }], + ['pposLong', { name: NDVars.pposLong, type: SimVarValueType.Degree }], + ['absoluteTime', { name: NDVars.absoluteTime, type: SimVarValueType.Seconds }], + ]) + + public constructor(bus: EventBus) { + super(NDSimvarPublisher.simvars, bus); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/animations.scss b/fbw-a380x/src/systems/instruments/src/ND/animations.scss new file mode 100644 index 00000000000..97f9bd61f66 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/animations.scss @@ -0,0 +1,71 @@ +@keyframes blinking { + 0% {opacity: 0;} + 50% {opacity: 0;} + 51% {opacity: 1;} + 100% {opacity: 1;} +} + +@mixin GenericPulsingStroke($color, $name) { + @keyframes #{$name} { + 0% {stroke: scale-color($color, $lightness: -30%);} + 50% {stroke: scale-color($color, $lightness: -30%);} + 51% {stroke: scale-color($color, $lightness: 30%);} + 100% {stroke: scale-color($color, $lightness: 30%);} + } + animation-name: $name; +} +@mixin GenericPulsingFill($color, $name) { + @keyframes #{$name} { + 0% {fill: scale-color($color, $lightness: -30%);} + 50% {fill: scale-color($color, $lightness: -30%);} + 51% {fill: scale-color($color, $lightness: 30%);} + 100% {fill: scale-color($color, $lightness: 30%);} + } + animation-name: $name; +} + +@keyframes OuterMarkerAnim { + 0% {opacity: 0;} + 33% {opacity: 0;} + 34% {opacity: 1;} + 100% {opacity: 1;} +} + +@keyframes MiddleMarkerAnim { + 0% {opacity: 0} + 10% {opacity: 0} + 11% {opacity: 1} + 27% {opacity: 1} + 28% {opacity: 0} + 44% {opacity: 0} + 45% {opacity: 1} + 100% {opacity: 1} +} + +.BlinkInfinite { + animation-name: blinking; + animation-duration: 1s; + animation-iteration-count: infinite; +} + +.Blink9Seconds { + animation-name: blinking; + animation-duration: 1s; + animation-iteration-count: 9; +} + +.OuterMarkerBlink { + animation-name: OuterMarkerAnim; + animation-duration: 460ms; + animation-iteration-count: infinite; +} +.MiddleMarkerBlink { + animation-name: MiddleMarkerAnim; + animation-duration: 730ms; + animation-iteration-count: infinite; +} +.InnerMarkerBlink { + animation-name: blinking; + animation-duration: 200ms; + animation-iteration-count: infinite; +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/config.json b/fbw-a380x/src/systems/instruments/src/ND/config.json new file mode 100644 index 00000000000..ade492578f8 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/config.json @@ -0,0 +1,4 @@ +{ + "index": "./instrument.tsx", + "isInteractive": false +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx b/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx new file mode 100644 index 00000000000..56fdbfa6499 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/instrument.tsx @@ -0,0 +1,172 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { Clock, FsBaseInstrument, FSComponent, FsInstrument, HEventPublisher, InstrumentBackplane, Subject } from '@microsoft/msfs-sdk'; +import { ArincEventBus, EfisSide } from '@flybywiresim/fbw-sdk'; +import { NDComponent } from '@flybywiresim/navigation-display'; + +import { NDSimvarPublisher, NDSimvars } from './NDSimvarPublisher'; +import { AdirsValueProvider } from '../MsfsAvionicsCommon/AdirsValueProvider'; +import { FmsDataPublisher } from '../MsfsAvionicsCommon/providers/FmsDataPublisher'; +import { FmsSymbolsPublisher } from './FmsSymbolsPublisher'; +import { VorBusPublisher } from '../MsfsAvionicsCommon/providers/VorBusPublisher'; +import { TcasBusPublisher } from '../MsfsAvionicsCommon/providers/TcasBusPublisher'; +import { FGDataPublisher } from '../MsfsAvionicsCommon/providers/FGDataPublisher'; +import { NDControlEvents } from './NDControlEvents'; +import { CdsDisplayUnit, DisplayUnitID, getDisplayIndex } from '../MsfsAvionicsCommon/CdsDisplayUnit'; +import { EgpwcBusPublisher } from '../MsfsAvionicsCommon/providers/EgpwcBusPublisher'; +import { DmcPublisher } from '../MsfsAvionicsCommon/providers/DmcPublisher'; +import { FMBusPublisher } from '../MsfsAvionicsCommon/providers/FMBusPublisher'; +import { FcuBusPublisher } from '../MsfsAvionicsCommon/providers/FcuBusPublisher'; + +import './style.scss'; + +class NDInstrument implements FsInstrument { + public readonly instrument: BaseInstrument; + + private readonly efisSide: EfisSide; + + private readonly bus: ArincEventBus; + + private readonly backplane = new InstrumentBackplane(); + + private readonly simVarPublisher: NDSimvarPublisher; + + private readonly fcuBusPublisher: FcuBusPublisher; + + private readonly fmsDataPublisher: FmsDataPublisher; + + private readonly fgDataPublisher: FGDataPublisher; + + private readonly fmBusPublisher: FMBusPublisher; + + private readonly fmsSymbolsPublisher: FmsSymbolsPublisher; + + private readonly vorBusPublisher: VorBusPublisher; + + private readonly tcasBusPublisher: TcasBusPublisher; + + private readonly dmcPublisher: DmcPublisher; + + private readonly egpwcBusPublisher: EgpwcBusPublisher; + + private readonly hEventPublisher; + + private readonly adirsValueProvider: AdirsValueProvider; + + private readonly clock: Clock; + + constructor() { + const side: EfisSide = getDisplayIndex() === 1 ? 'L' : 'R'; + const stateSubject = Subject.create<'L' | 'R'>(side); + this.efisSide = side; + + this.bus = new ArincEventBus(); + + this.simVarPublisher = new NDSimvarPublisher(this.bus); + this.fcuBusPublisher = new FcuBusPublisher(this.bus, side); + this.fmsDataPublisher = new FmsDataPublisher(this.bus, stateSubject); + this.fgDataPublisher = new FGDataPublisher(this.bus); + this.fmBusPublisher = new FMBusPublisher(this.bus); + this.fmsSymbolsPublisher = new FmsSymbolsPublisher(this.bus, side); + this.vorBusPublisher = new VorBusPublisher(this.bus); + this.tcasBusPublisher = new TcasBusPublisher(this.bus); + this.dmcPublisher = new DmcPublisher(this.bus); + this.egpwcBusPublisher = new EgpwcBusPublisher(this.bus, side); + this.hEventPublisher = new HEventPublisher(this.bus); + + this.adirsValueProvider = new AdirsValueProvider(this.bus, this.simVarPublisher, side); + + this.clock = new Clock(this.bus); + + this.backplane.addPublisher('ndSimVars', this.simVarPublisher); + this.backplane.addPublisher('fcu', this.fcuBusPublisher); + this.backplane.addPublisher('fms', this.fmsDataPublisher); + this.backplane.addPublisher('fg', this.fgDataPublisher); + this.backplane.addPublisher('fms-arinc', this.fmBusPublisher); + this.backplane.addPublisher('fms-symbols', this.fmsSymbolsPublisher); + this.backplane.addPublisher('vor', this.vorBusPublisher); + this.backplane.addPublisher('tcas', this.tcasBusPublisher); + this.backplane.addPublisher('dmc', this.dmcPublisher); + this.backplane.addPublisher('egpwc', this.egpwcBusPublisher); + + this.backplane.addInstrument('clock', this.clock); + + this.doInit(); + } + + private doInit(): void { + this.backplane.init(); + + this.dmcPublisher.init(); + + this.adirsValueProvider.start(); + + FSComponent.render( + + + , + document.getElementById('ND_CONTENT'), + ); + + // Remove "instrument didn't load" text + document.getElementById('ND_CONTENT').querySelector(':scope > h1').remove(); + } + + /** + * A callback called when the instrument gets a frame update. + */ + public Update(): void { + this.backplane.onUpdate(); + } + + public onInteractionEvent(args: string[]): void { + if (args[0].endsWith(`A32NX_EFIS_${this.efisSide}_CHRONO_PUSHED`)) { + this.bus.getPublisher().pub('chrono_pushed', undefined); + } + + this.hEventPublisher.dispatchHEvent(args[0]); + } + + onGameStateChanged(_oldState: GameState, _newState: GameState) { + // noop + } + + onFlightStart() { + // noop + } + + onSoundEnd(_soundEventId: Name_Z) { + // noop + } +} + +class A380X_ND extends FsBaseInstrument { + constructInstrument(): NDInstrument { + return new NDInstrument(); + } + + get isInteractive(): boolean { + return false; + } + + get templateID(): string { + return 'A380X_ND'; + } +} + +// Hack to support tspan SVG elements, which FSComponent does not recognise as SVG + +const original = document.createElement.bind(document); + +const extraSvgTags = ['tspan']; + +document.createElement = ((tagName, options) => { + if (extraSvgTags.includes(tagName)) { + return document.createElementNS('http://www.w3.org/2000/svg', tagName, options); + } + return original(tagName, options); +}) as any; + +registerInstrument('a380x-nd', A380X_ND); diff --git a/fbw-a32nx/src/systems/instruments/src/ND_legacy/styles.scss b/fbw-a380x/src/systems/instruments/src/ND/style.scss similarity index 62% rename from fbw-a32nx/src/systems/instruments/src/ND_legacy/styles.scss rename to fbw-a380x/src/systems/instruments/src/ND/style.scss index 0867d1fbd09..fc9a2c06839 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND_legacy/styles.scss +++ b/fbw-a380x/src/systems/instruments/src/ND/style.scss @@ -1,4 +1,5 @@ -@import "../Common/definitions"; +@import "../MsfsAvionicsCommon/definitions.scss"; +@import "animations"; @font-face { font-family: "Ecam"; @@ -18,38 +19,81 @@ .nd-svg { position: absolute; + top: 0; + left: 0; width: 768px; height: 768px; background: transparent; font-family: "Ecam", monospace !important; } -.nd-inverted-map-area { - background: $display-background; - fill: rgb(4,4,4); +.nd-canvas-map { + transform: rotateX(0deg); +} + +.nd-top-layer { + transform: rotateX(0deg); + background: none; +} + +.TextOutline { + paint-order: stroke fill markers; + + stroke-width: 0.05mm; + stroke: $display-background !important; +} + +$font-factor: 5; + +.FontLargest { + font-size: #{7px * $font-factor}; +} + +.FontLarge { + font-size: #{6.5px * $font-factor}; +} + +.FontMedium { + font-size: #{6px * $font-factor}; +} + +.FontIntermediate { + font-size: #{5.5px * $font-factor}; } -.GtLayer { - -webkit-transform: rotateX(0deg); +.FontSmall { + font-size: #{5px * $font-factor}; } +.FontSmallest { + font-size: #{4.5px * $font-factor}; +} + +.FontTiny { + font-size: #{4px * $font-factor}; +} + +.StartAlign { + text-align: start; + text-anchor: start; +} .MiddleAlign { + text-align: center; text-anchor: middle; } +.EndAlign { + text-align: end; + text-anchor: end; +} .Magenta { fill: none; stroke: $display-magenta; } - -// Used for the speed change dot -.Magenta.Fill { - fill: $display-magenta; - stroke: none; -} - +text.Magenta, +tspan.Magenta, .Magenta text, -text.Magenta { +.Magenta tspan { fill: $display-magenta; stroke: none; } @@ -58,37 +102,31 @@ text.Magenta { fill: none; stroke: $display-cyan; } - -.Cyan.Fill { - fill: $display-cyan; - stroke: none; -} - -.Cyan text, text.Cyan, -.Cyan tspan, -tspan.Cyan { +tspan.Cyan, +.Cyan text, +.Cyan tspan { fill: $display-cyan; stroke: none; } -tspan.Cyan { - fill: $display-cyan; +/* .None { + fill: none; stroke: none; -} +} */ .White { fill: none; stroke: $display-white; } - .White.Fill { fill: $display-white; stroke: none; } - +text.White, +tspan.White, .White text, -text.White { +.White tspan { fill: $display-white; stroke: none; } @@ -103,10 +141,10 @@ text.White { stroke: none; } -.Green text, text.Green, -.Green tspan, -tspan.Green { +tspan.Green, +.Green text, +.Green tspan { fill: $display-green; stroke: none; } @@ -115,9 +153,10 @@ tspan.Green { stroke: $display-amber; fill: none; } - +text.Amber, +tspan.Amber, .Amber text, -text.Amber { +.Amber tspan { fill: $display-amber; stroke: none; } @@ -126,14 +165,14 @@ text.Amber { stroke: $display-yellow; fill: none; } - .Yellow.Fill { fill: $display-yellow; stroke: none; } - +text.Yellow, +tspan.Yellow, .Yellow text, -text.Yellow { +.Yellow tspan { fill: $display-yellow; stroke: none; } @@ -142,30 +181,31 @@ text.Yellow { stroke: $display-red; fill: none; } - .Red.Fill { fill: $display-red; stroke: none; } - +text.Red, +tspan.Red, .Red text, -text.Red { +.Red tspan { fill: $display-red; stroke: none; } +.Grey { + stroke: $display-grey; + fill: none; +} .Grey.Fill { fill: $display-grey; stroke: none; } + .BackgroundFill { fill: $display-background; -} - -path.rounded { - stroke-linecap: round; - stroke-linejoin: round; + fill-rule: evenodd; } text.shadow { @@ -182,6 +222,17 @@ rect.shadow { fill: none; } + .chrono { font-family: "NDChrono", monospace !important; } + +.nd-inverted-map-area { + background: $display-background; + fill: rgb(4,4,5); +} + +path.rounded { + stroke-linecap: round; + stroke-linejoin: round; +} diff --git a/fbw-a380x/src/systems/instruments/src/ND/tsconfig.json b/fbw-a380x/src/systems/instruments/src/ND/tsconfig.json new file mode 100644 index 00000000000..a66548247a2 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/ND/tsconfig.json @@ -0,0 +1,34 @@ +{ + "extends": "../../../tsconfig.json", + + "compilerOptions": { + "incremental": false /* Enables incremental builds */, + "target": "es2017" /* Specifies the ES2017 target, compatible with Coherent GT */, + "module": "es2015" /* Ensures that modules are at least es2015 */, + "strict": false /* Enables strict type checking, highly recommended but optional */, + "esModuleInterop": true /* Emits additional JS to work with CommonJS modules */, + "skipLibCheck": true /* Skip type checking on library .d.ts files */, + "forceConsistentCasingInFileNames": true /* Ensures correct import casing */, + "moduleResolution": "node" /* Enables compatibility with MSFS SDK bare global imports */, + "jsxFactory": "FSComponent.buildComponent" /* Required for FSComponent framework JSX */, + "jsxFragmentFactory": "FSComponent.Fragment" /* Required for FSComponent framework JSX */, + "jsx": "react", /* Required for FSComponent framework JSX */ + "paths": { + "@datalink/aoc": ["../../../fbw-common/src/systems/datalink/aoc/src/index.ts"], + "@datalink/atc": ["../../../fbw-common/src/systems/datalink/atc/src/index.ts"], + "@datalink/common": ["../../../fbw-common/src/systems/datalink/common/src/index.ts"], + "@datalink/router": ["../../../fbw-common/src/systems/datalink/router/src/index.ts"], + "@failures": ["./failures/src/index.ts"], + "@fmgc/*": ["./fmgc/src/*"], + "@instruments/common/*": ["./instruments/src/Common/*"], + "@localization/*": ["../localization/*"], + "@sentry/*": ["./sentry-client/src/*"], + "@simbridge/*": ["./simbridge-client/src/*"], + "@shared/*": ["./shared/src/*"], + "@tcas/*": ["./tcas/src/*"], + "@typings/*": ["../../../fbw-common/src/typings/*"], + "@flybywiresim/fbw-sdk": ["../../../fbw-common/src/systems/index-no-react.ts"], + "@flybywiresim/navigation-display": ["../../../fbw-common/src/systems/instruments/src/ND/index.ts"] + } + } +} diff --git a/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx b/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx index 233f88efc26..6ec573e9a87 100644 --- a/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx +++ b/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; // import { useInteractionEvent } from '@instruments/common/hooks'; import { useSimVar } from '@instruments/common/simVars'; -import { CdsDisplayUnit, DisplayUnitID } from '@instruments/common/CdsDisplayUnit'; +import { LegacyCdsDisplayUnit, DisplayUnitID } from '@instruments/common/LegacyCdsDisplayUnit'; // import { getSimVar } from '../util'; import { EngPage } from './Pages/Engine/EngPage'; @@ -55,11 +55,11 @@ export const SystemDisplay = () => { }; return ( - + {PAGES[theCurrentPage]} - + ); }; diff --git a/fbw-a380x/src/systems/tsconfig.json b/fbw-a380x/src/systems/tsconfig.json index 7ca63c85442..2fc8384bb8c 100644 --- a/fbw-a380x/src/systems/tsconfig.json +++ b/fbw-a380x/src/systems/tsconfig.json @@ -1,9 +1,15 @@ { "compilerOptions": { - "target": "ESNext", - "baseUrl": ".", - "typeRoots": ["../typings", "../node_modules/@types"], - "moduleResolution": "node", + "target": "ES2017", + "baseUrl": ".", + "resolveJsonModule" : true, + "skipLibCheck": true, + "typeRoots": [ + "../../../fbw-common/src/typings" + ], + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "jsx": "react", "paths": { "@shared/*": ["./shared/src/*"], "@instruments/common/*": ["./instruments/src/Common/*"], @@ -11,7 +17,8 @@ "@fmgc/*": ["./fmgc/src/*"], "@flybywiresim/failures": ["failures"], "@tcas/*": ["./tcas/src/*"], - "@typings/*": ["../typings"] + "@typings/*": ["../typings"], + "@flybywiresim/fbw-sdk": ["../../../fbw-common/src/systems/index.ts"] } } } diff --git a/fbw-common/src/.eslintrc.js b/fbw-common/src/.eslintrc.js index 0bbe6059b82..633b797af99 100644 --- a/fbw-common/src/.eslintrc.js +++ b/fbw-common/src/.eslintrc.js @@ -80,9 +80,9 @@ module.exports = { 'import/no-unresolved': 'off', '@typescript-eslint/no-unused-vars': ['error', { vars: 'all', - varsIgnorePattern: '^_', + varsIgnorePattern: '^_|^FSComponent$', args: 'after-used', - argsIgnorePattern: '^_', + argsIgnorePattern: '^_|^node$|^deltaTime$', }], 'no-use-before-define': 'off', diff --git a/fbw-common/src/systems/instruments/src/ND/.eslintrc.js b/fbw-common/src/systems/instruments/src/ND/.eslintrc.js new file mode 100644 index 00000000000..a179e67667f --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/.eslintrc.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = { + extends: '../../../../.eslintrc.js', + + // overrides airbnb, use sparingly + rules: { 'react/no-unknown-property': 'off', 'react/style-prop-object': 'off', 'arrow-body-style': 'off', 'camelcase': 'off' }, +}; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/Chrono.tsx b/fbw-common/src/systems/instruments/src/ND/Chrono.tsx similarity index 99% rename from fbw-a32nx/src/systems/instruments/src/ND/Chrono.tsx rename to fbw-common/src/systems/instruments/src/ND/Chrono.tsx index be18dff5a46..7dca659c789 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/Chrono.tsx +++ b/fbw-common/src/systems/instruments/src/ND/Chrono.tsx @@ -1,4 +1,5 @@ import { FSComponent, DisplayComponent, Subject, VNode, ComponentProps, EventBus } from '@microsoft/msfs-sdk'; + import { NDControlEvents } from './NDControlEvents'; import { NDSimvars } from './NDSimvarPublisher'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/FmMessages.tsx b/fbw-common/src/systems/instruments/src/ND/FmMessages.tsx similarity index 91% rename from fbw-a32nx/src/systems/instruments/src/ND/FmMessages.tsx rename to fbw-common/src/systems/instruments/src/ND/FmMessages.tsx index 4bd9d4bb958..dea3887f3e4 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/FmMessages.tsx +++ b/fbw-common/src/systems/instruments/src/ND/FmMessages.tsx @@ -1,8 +1,13 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { ArraySubject, DisplayComponent, EventBus, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { FMMessage, FMMessageTypes } from '@shared/FmMessages'; -import { EfisNdMode } from '@shared/NavigationDisplay'; -import { Layer } from '../MsfsAvionicsCommon/Layer'; -import { FmsVars } from '../MsfsAvionicsCommon/providers/FmsDataPublisher'; +import { FMMessage, FMMessageTypes } from '@flybywiresim/fbw-sdk'; + +import { EfisNdMode } from '../NavigationDisplay'; +import { Layer } from './Layer'; +import { GenericFmsEvents } from './types/GenericFmsEvents'; export interface FmMessagesProps { bus: EventBus, @@ -32,7 +37,7 @@ export class FmMessages extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); this.activeMessages.sub((_, type, ___, array) => { this.lastActiveMessage.set(array[array.length - 1]); diff --git a/fbw-common/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts b/fbw-common/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts new file mode 100644 index 00000000000..662f0b8b448 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/FmsSymbolsPublisher.ts @@ -0,0 +1,13 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { NdSymbol, NdTraffic, PathVector } from '@flybywiresim/fbw-sdk'; + +export interface FmsSymbolsData { + symbols: NdSymbol[], + vectorsActive: PathVector[], + vectorsDashed: PathVector[], + vectorsTemporary: PathVector[], + traffic: NdTraffic[], +} diff --git a/fbw-common/src/systems/instruments/src/ND/Layer.tsx b/fbw-common/src/systems/instruments/src/ND/Layer.tsx new file mode 100644 index 00000000000..29609e8210c --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/Layer.tsx @@ -0,0 +1,29 @@ +import { FSComponent, DisplayComponent, VNode, Subscribable, MappedSubject, ComponentProps } from '@microsoft/msfs-sdk'; + +export interface LayerProps extends ComponentProps { + x: number | Subscribable; + y: number | Subscribable; + visible?: Subscribable; +} + +export class Layer extends DisplayComponent { + render(): VNode | null { + const { x, y } = this.props; + const ref = this.props.ref ?? FSComponent.createRef(); + + let value: Subscribable | string; + if (typeof x !== 'number' && typeof y !== 'number') { + value = MappedSubject.create(([x, y]) => `translate(${x}, ${y})`, x, y); + } else if (typeof x !== 'number' || typeof y !== 'number') { + throw new Error('Both attributes of Layer must be of the same type (number or Subscribable)'); + } else { + value = `translate(${x}, ${y})`; + } + + return ( + (v ? 'inherit' : 'hidden')) ?? 'inherit'}> + {this.props.children} + + ); + } +} diff --git a/fbw-a32nx/src/systems/instruments/src/ND/ND.tsx b/fbw-common/src/systems/instruments/src/ND/ND.tsx similarity index 91% rename from fbw-a32nx/src/systems/instruments/src/ND/ND.tsx rename to fbw-common/src/systems/instruments/src/ND/ND.tsx index 69286394303..0f0283f11b0 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/ND.tsx +++ b/fbw-common/src/systems/instruments/src/ND/ND.tsx @@ -3,22 +3,16 @@ // SPDX-License-Identifier: GPL-3.0 import { ClockEvents, ConsumerSubject, DisplayComponent, EventBus, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { SimVarString } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, EfisNdRangeValue, EfisSide, rangeSettings } from '@shared/NavigationDisplay'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; + import { clampAngle } from 'msfs-geo'; -import { ArincEventBus } from 'instruments/src/MsfsAvionicsCommon/ArincEventBus'; -import { CrossTrackError } from 'instruments/src/ND/shared/CrossTrackError'; -import { FmsVars } from 'instruments/src/MsfsAvionicsCommon/providers/FmsDataPublisher'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { RadioNeedle } from 'instruments/src/ND/shared/RadioNeedle'; -import { getSmallestAngle } from 'instruments/src/PFD/PFDUtils'; -import { SelectedHeadingBug } from 'instruments/src/ND/pages/arc/SelectedHeadingBug'; -import { DisplayUnit } from '../MsfsAvionicsCommon/displayUnit'; -import { AdirsSimVars } from '../MsfsAvionicsCommon/SimVarTypes'; +import { CrossTrackError } from './shared/CrossTrackError'; +import { RadioNeedle } from './shared/RadioNeedle'; +import { SelectedHeadingBug } from './pages/arc/SelectedHeadingBug'; +import { GenericFmsEvents } from './types/GenericFmsEvents'; +import { GenericAdirsEvents } from './types/GenericAdirsEvents'; import { NDSimvars } from './NDSimvarPublisher'; import { ArcModePage } from './pages/arc'; -import { Layer } from '../MsfsAvionicsCommon/Layer'; +import { Layer } from './Layer'; import { FmMessages } from './FmMessages'; import { Flag, FlagProps } from './shared/Flag'; import { CanvasMap } from './shared/map/CanvasMap'; @@ -31,19 +25,25 @@ import { RoseVorPage } from './pages/rose/RoseVorPage'; import { NDControlEvents } from './NDControlEvents'; import { Airplane } from './shared/Airplane'; import { TcasWxrMessages } from './TcasWxrMessages'; -import { Arinc429RegisterSubject } from '../MsfsAvionicsCommon/Arinc429RegisterSubject'; import { Chrono } from './Chrono'; import { WindIndicator } from './shared/WindIndicator'; import { TerrainMapThresholds } from './TerrainMapThresholds'; -import { Arinc429ConsumerSubject } from '../MsfsAvionicsCommon/Arinc429ConsumerSubject'; import { TrackLine } from './shared/TrackLine'; import { TrackBug } from './shared/TrackBug'; +import { GenericFcuEvents } from './types/GenericFcuEvents'; +import { ArincEventBus } from '../../../shared/src/ArincEventBus'; +import { EfisNdMode, EfisSide, EfisNdRangeValue, efisRangeSettings } from '../NavigationDisplay'; +import { Arinc429RegisterSubject } from '../../../shared/src/Arinc429RegisterSubject'; +import { Arinc429ConsumerSubject } from '../../../shared/src/Arinc429ConsumerSubject'; +import { MathUtils } from '../../../shared/src/MathUtils'; +import { SimVarString } from '../../../shared/src/simvar'; +import { GenericDisplayManagementEvents } from './types/GenericDisplayManagementEvents'; const PAGE_GENERATION_BASE_DELAY = 500; const PAGE_GENERATION_RANDOM_DELAY = 70; export const getDisplayIndex = () => { - const url = document.getElementsByTagName('a32nx-nd')[0].getAttribute('url'); + const url = document.querySelector('vcockpit-panel > *').getAttribute('url'); return url ? parseInt(url.substring(url.length - 1), 10) : 0; }; @@ -54,12 +54,6 @@ export interface NDProps { } export class NDComponent extends DisplayComponent { - private displayBrightness = Subject.create(0); - - private displayFailed = Subject.create(false); - - private displayPowered = Subject.create(false); - private readonly pposLatWord = Arinc429RegisterSubject.createEmpty() private readonly pposLonWord = Arinc429RegisterSubject.createEmpty() @@ -102,9 +96,7 @@ export class NDComponent extends DisplayComponent { private rangeChangeInvalidationTimeout = -1; - private readonly mapRecomputing = MappedSubject.create(([pageChange, rangeChange]) => { - return pageChange || rangeChange; - }, this.pageChangeInProgress, this.rangeChangeInProgress); + private readonly mapRecomputing = MappedSubject.create(([pageChange, rangeChange]) => pageChange || rangeChange, this.pageChangeInProgress, this.rangeChangeInProgress); private readonly trkFlagShown = MappedSubject.create(([isUsingTrackUpMode, trackWord, currentPageMode]) => { if (currentPageMode === EfisNdMode.PLAN) { @@ -129,22 +121,12 @@ export class NDComponent extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const isCaptainSide = getDisplayIndex() === 1; - this.currentPageInstance = this.arcPage.instance; this.currentPageInstance.isVisible.set(true); this.currentPageInstance.onShow(); - const sub = this.props.bus.getSubscriber(); - - sub.on(isCaptainSide ? 'potentiometerCaptain' : 'potentiometerFo').whenChanged().handle((value) => { - this.displayBrightness.set(value); - }); - - sub.on(isCaptainSide ? 'elec' : 'elecFo').whenChanged().handle((value) => { - this.displayPowered.set(value); - }); + const sub = this.props.bus.getSubscriber(); sub.on('trueHeadingRaw').whenChanged().handle((value) => { this.trueHeadingWord.setWord(value); @@ -169,7 +151,7 @@ export class NDComponent extends DisplayComponent { sub.on('trueRefActive').whenChanged().handle((v) => this.trueRefActive.set(v)); sub.on('ndRangeSetting').whenChanged().handle((value) => { - this.mapRangeRadius.set(rangeSettings[value]); + this.mapRangeRadius.set(efisRangeSettings[value]); this.invalidateRange(); }); @@ -182,6 +164,7 @@ export class NDComponent extends DisplayComponent { }); } + // eslint-disable-next-line arrow-body-style private readonly mapFlagShown = MappedSubject.create(([headingWord, latWord, longWord, currentPageMode]) => { return (!headingWord.isNormalOperation() || !latWord.isNormalOperation() || !longWord.isNormalOperation()) && currentPageMode !== EfisNdMode.PLAN; }, this.headingWord, this.pposLatWord, this.pposLonWord, this.currentPageMode); @@ -190,7 +173,7 @@ export class NDComponent extends DisplayComponent { if (isUsingTrackUpMode) { if (headingWord.isNormalOperation() && trackWord.isNormalOperation()) { // FIXME move that file to MsfsAvionicsCommon or another shared folder - return getSmallestAngle(headingWord.value, trackWord.value); + return MathUtils.getSmallestAngle(headingWord.value, trackWord.value); } } @@ -270,7 +253,7 @@ export class NDComponent extends DisplayComponent { render(): VNode | null { return ( - + <> {/* ND Vector graphics - bottom layer */} { !it)} /> - (m === EfisNdMode.ARC ? 'url(#arc-mode-map-clip)' : ''))}> + (m === EfisNdMode.ARC ? 'url(#arc-mode-map-clip)' : ''))}> { - + ); } } @@ -417,7 +400,7 @@ class SpeedIndicator extends DisplayComponent<{ bus: EventBus }> { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('groundSpeed').atFrequency(2).handle((value) => this.groundSpeedRegister.setWord(value)); @@ -492,7 +475,7 @@ class TrueFlag extends DisplayComponent { width={68} height={23} class={this.props.class} - stroke-width={1.5} + strokeWidth={1.5} ref={this.boxRef} /> @@ -516,7 +499,7 @@ class GridTrack extends DisplayComponent { render(): VNode | null { return ( - + â—‡ @@ -533,7 +516,7 @@ class GridTrack extends DisplayComponent { } class TopMessages extends DisplayComponent<{ bus: EventBus, ndMode: Subscribable }> { - private readonly sub = this.props.bus.getSubscriber(); + private readonly sub = this.props.bus.getSubscriber(); private readonly trueRefActive = Subject.create(false); @@ -642,7 +625,7 @@ interface ToWaypointIndicatorProps { } class ToWaypointIndicator extends DisplayComponent { - private readonly sub = this.props.bus.getSubscriber(); + private readonly sub = this.props.bus.getSubscriber(); private readonly trueRefActive = ConsumerSubject.create(null, false); @@ -669,9 +652,7 @@ class ToWaypointIndicator extends DisplayComponent { private readonly visibleSub = Subject.create(false); private readonly bearingContainerVisible = MappedSubject.create( - ([trueRef, bearing, trueBearing, isNormalOperation]) => { - return isNormalOperation && Number.isFinite(trueRef ? trueBearing : bearing); - }, + ([trueRef, bearing, trueBearing, isNormalOperation]) => isNormalOperation && Number.isFinite(trueRef ? trueBearing : bearing), this.trueRefActive, this.bearing, this.trueBearing, diff --git a/fbw-common/src/systems/instruments/src/ND/NDControlEvents.ts b/fbw-common/src/systems/instruments/src/ND/NDControlEvents.ts new file mode 100644 index 00000000000..f35c8bd11ee --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/NDControlEvents.ts @@ -0,0 +1,80 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +/** + * Events for internal ND communication between components + */ +import { EfisNdMode } from '@flybywiresim/fbw-sdk'; + +export interface NDControlEvents { + /** + * Set if the plane icon is visible + */ + set_show_plane: boolean, + + /** + * Set the X position of the plane icon (0 to 786) + */ + set_plane_x: number, + + /** + * Set the Y position of the plane icon (0 to 786) + */ + set_plane_y: number, + + /** + * Set the rotation of the plane icon (degrees) + */ + set_plane_rotation: number, + + /** + * Set if the map is visible + */ + set_show_map: boolean, + + /** + * Set if the map is recomputing (RANGE CHANGE, MODE CHANGE) + */ + set_map_recomputing: boolean, + + /** + * Set the center latitude of the map + */ + set_map_center_lat: number, + + /** + * Set the center longitude of the map + */ + set_map_center_lon: number, + + /** + * Set the center Y-axis bias of the map + */ + set_map_center_y_bias: number, + + /** + * Set the true course up of the map + */ + set_map_up_course: number, + + /** + * Set the pixel radius of the map + */ + set_map_pixel_radius: number, + + /** + * Set the range radius of the map + */ + set_map_range_radius: number, + + /** + * Set the EFIS ND mode of the map + */ + set_map_efis_mode: EfisNdMode, + + /** + * Event for the CHRONO button being pushed + */ + chrono_pushed: void, +} diff --git a/fbw-common/src/systems/instruments/src/ND/NDSimvarPublisher.tsx b/fbw-common/src/systems/instruments/src/ND/NDSimvarPublisher.tsx new file mode 100644 index 00000000000..e80249eeecf --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/NDSimvarPublisher.tsx @@ -0,0 +1,16 @@ +import { GenericAdirsEvents } from './types/GenericAdirsEvents'; +import { GenericSwitchingPanelEvents } from './types/GenericSwitchingPanelEvents'; + +export type NDSimvars = GenericAdirsEvents & GenericSwitchingPanelEvents & { + elec: boolean; + elecFo: boolean; + potentiometerCaptain: number; + potentiometerFo: number; + ilsCourse: number; + selectedWaypointLat: Degrees; + selectedWaypointLong: Degrees; + selectedHeading: Degrees; + pposLat: Degrees; + pposLong: Degrees; + absoluteTime: Seconds; + } diff --git a/fbw-a32nx/src/systems/instruments/src/ND/TcasWxrMessages.tsx b/fbw-common/src/systems/instruments/src/ND/TcasWxrMessages.tsx similarity index 90% rename from fbw-a32nx/src/systems/instruments/src/ND/TcasWxrMessages.tsx rename to fbw-common/src/systems/instruments/src/ND/TcasWxrMessages.tsx index fb44a9aa825..26d539da977 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/TcasWxrMessages.tsx +++ b/fbw-common/src/systems/instruments/src/ND/TcasWxrMessages.tsx @@ -1,7 +1,12 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, VNode, Subject, MappedSubject, EventBus, Subscribable } from '@microsoft/msfs-sdk'; -import { EfisNdMode, TcasWxrMessage } from '@shared/NavigationDisplay'; -import { Layer } from '../MsfsAvionicsCommon/Layer'; -import { TcasSimVars } from '../MsfsAvionicsCommon/providers/TcasBusPublisher'; + +import { EfisNdMode, TcasWxrMessage } from '@flybywiresim/fbw-sdk'; +import { Layer } from './Layer'; +import { GenericTcasEvents } from './types/GenericTcasEvents'; export interface TcasWXMessagesProps { bus: EventBus, @@ -30,7 +35,7 @@ export class TcasWxrMessages extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('tcasTaOnly').whenChanged().handle((value) => this.taOnlySub.set(value)); sub.on('tcasFault').whenChanged().handle((value) => this.failSub.set(value)); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/TerrainMapThresholds.tsx b/fbw-common/src/systems/instruments/src/ND/TerrainMapThresholds.tsx similarity index 94% rename from fbw-a32nx/src/systems/instruments/src/ND/TerrainMapThresholds.tsx rename to fbw-common/src/systems/instruments/src/ND/TerrainMapThresholds.tsx index e46772de844..51c47533aa4 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/TerrainMapThresholds.tsx +++ b/fbw-common/src/systems/instruments/src/ND/TerrainMapThresholds.tsx @@ -1,12 +1,13 @@ import { FSComponent, ConsumerSubject, DisplayComponent, EventBus, VNode, MappedSubject } from '@microsoft/msfs-sdk'; -import { EgpwcSimVars, TerrainLevelMode } from '../MsfsAvionicsCommon/providers/EgpwcBusPublisher'; + +import { GenericTawsEvents, TerrainLevelMode } from './types/GenericTawsEvents'; export interface TerrainMapThresholdsProps { bus: EventBus, } export class TerrainMapThresholds extends DisplayComponent { - private readonly sub = this.props.bus.getSubscriber(); + private readonly sub = this.props.bus.getSubscriber(); private readonly maxElevationSub = ConsumerSubject.create(this.sub.on('egpwc.maxElevation'), -1); diff --git a/fbw-common/src/systems/instruments/src/ND/animations.scss b/fbw-common/src/systems/instruments/src/ND/animations.scss new file mode 100644 index 00000000000..97f9bd61f66 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/animations.scss @@ -0,0 +1,71 @@ +@keyframes blinking { + 0% {opacity: 0;} + 50% {opacity: 0;} + 51% {opacity: 1;} + 100% {opacity: 1;} +} + +@mixin GenericPulsingStroke($color, $name) { + @keyframes #{$name} { + 0% {stroke: scale-color($color, $lightness: -30%);} + 50% {stroke: scale-color($color, $lightness: -30%);} + 51% {stroke: scale-color($color, $lightness: 30%);} + 100% {stroke: scale-color($color, $lightness: 30%);} + } + animation-name: $name; +} +@mixin GenericPulsingFill($color, $name) { + @keyframes #{$name} { + 0% {fill: scale-color($color, $lightness: -30%);} + 50% {fill: scale-color($color, $lightness: -30%);} + 51% {fill: scale-color($color, $lightness: 30%);} + 100% {fill: scale-color($color, $lightness: 30%);} + } + animation-name: $name; +} + +@keyframes OuterMarkerAnim { + 0% {opacity: 0;} + 33% {opacity: 0;} + 34% {opacity: 1;} + 100% {opacity: 1;} +} + +@keyframes MiddleMarkerAnim { + 0% {opacity: 0} + 10% {opacity: 0} + 11% {opacity: 1} + 27% {opacity: 1} + 28% {opacity: 0} + 44% {opacity: 0} + 45% {opacity: 1} + 100% {opacity: 1} +} + +.BlinkInfinite { + animation-name: blinking; + animation-duration: 1s; + animation-iteration-count: infinite; +} + +.Blink9Seconds { + animation-name: blinking; + animation-duration: 1s; + animation-iteration-count: 9; +} + +.OuterMarkerBlink { + animation-name: OuterMarkerAnim; + animation-duration: 460ms; + animation-iteration-count: infinite; +} +.MiddleMarkerBlink { + animation-name: MiddleMarkerAnim; + animation-duration: 730ms; + animation-iteration-count: infinite; +} +.InnerMarkerBlink { + animation-name: blinking; + animation-duration: 200ms; + animation-iteration-count: infinite; +} diff --git a/fbw-common/src/systems/instruments/src/ND/index.ts b/fbw-common/src/systems/instruments/src/ND/index.ts new file mode 100644 index 00000000000..878ce26a659 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/index.ts @@ -0,0 +1 @@ +export * from './ND'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/NDPage.tsx b/fbw-common/src/systems/instruments/src/ND/pages/NDPage.tsx similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/NDPage.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/NDPage.tsx diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx b/fbw-common/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx similarity index 94% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx index 20f53f8e4a9..cf6dee176d5 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/arc/ArcModeUnderlay.tsx @@ -2,12 +2,11 @@ // // SPDX-License-Identifier: GPL-3.0 -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { DisplayComponent, EventBus, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { MathUtils } from '@flybywiresim/fbw-sdk'; -import { rangeSettings } from '@shared/NavigationDisplay'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { TcasSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/TcasBusPublisher'; +import { DisplayComponent, EventBus, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; +import { MathUtils, efisRangeSettings } from '@flybywiresim/fbw-sdk'; + +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; +import { GenericTcasEvents } from '../../types/GenericTcasEvents'; export interface ArcModeOverlayProps { bus: EventBus, @@ -29,10 +28,10 @@ export class ArcModeUnderlay extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('ndRangeSetting').whenChanged().handle((value) => { - this.rangeValue.set(rangeSettings[value]); + this.rangeValue.set(efisRangeSettings[value]); this.handleRingVisibilities(); }); @@ -127,20 +126,20 @@ export class ArcModeUnderlay extends DisplayComponent { - - - - - + + + + + {/* R = 62 */} - - - - - + + + + + diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx b/fbw-common/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx similarity index 78% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx index 68d9c8da412..dc5ce8412cb 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/arc/LsCourseBug.tsx @@ -1,11 +1,13 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, MappedSubject, Subject, Subscribable, VNode, ConsumerSubject } from '@microsoft/msfs-sdk'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { ArincEventBus } from 'instruments/src/MsfsAvionicsCommon/ArincEventBus'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { EfisNdMode } from '@shared/NavigationDisplay'; +import { ArincEventBus, EfisNdMode, Arinc429ConsumerSubject, MathUtils } from '@flybywiresim/fbw-sdk'; + import { NDSimvars } from '../../NDSimvarPublisher'; -import { getSmallestAngle } from '../../../PFD/PFDUtils'; -import { Arinc429ConsumerSubject } from '../../../MsfsAvionicsCommon/Arinc429ConsumerSubject'; +import { GenericDisplayManagementEvents } from '../../types/GenericDisplayManagementEvents'; +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; export interface LsCourseBugProps { bus: ArincEventBus, @@ -37,7 +39,7 @@ export class LsCourseBug extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getArincSubscriber(); + const sub = this.props.bus.getArincSubscriber(); this.headingWord.setConsumer(sub.on('heading').withArinc429Precision(2)); @@ -65,7 +67,7 @@ export class LsCourseBug extends DisplayComponent { const headingValid = this.headingWord.get().isNormalOperation(); if (headingValid) { - const diff = getSmallestAngle(this.lsCourse.get(), this.headingWord.get().value); + const diff = MathUtils.getSmallestAngle(this.lsCourse.get(), this.headingWord.get().value); this.diffSubject.set(diff + this.props.rotationOffset.get()); } @@ -81,8 +83,8 @@ export class LsCourseBug extends DisplayComponent { - - + + ); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx b/fbw-common/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx similarity index 91% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx index a9a7e091065..8e24de0f394 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/arc/LubberLine.tsx @@ -1,5 +1,9 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, VNode, EventBus, Subscribable } from '@microsoft/msfs-sdk'; -import { EfisNdMode } from '@shared/NavigationDisplay'; +import { EfisNdMode } from '@flybywiresim/fbw-sdk'; export interface LubberLineProps { bus: EventBus, diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx b/fbw-common/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx similarity index 85% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx index 5e7845b54d5..2e1baeab40a 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/arc/SelectedHeadingBug.tsx @@ -1,10 +1,12 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { ArincEventBus } from 'instruments/src/MsfsAvionicsCommon/ArincEventBus'; -import { EfisNdMode } from '@shared/NavigationDisplay'; +import { ArincEventBus, EfisNdMode, Arinc429ConsumerSubject, MathUtils } from '@flybywiresim/fbw-sdk'; + import { NDSimvars } from '../../NDSimvarPublisher'; -import { getSmallestAngle } from '../../../PFD/PFDUtils'; -import { Arinc429ConsumerSubject } from '../../../MsfsAvionicsCommon/Arinc429ConsumerSubject'; +import { GenericDisplayManagementEvents } from '../../types/GenericDisplayManagementEvents'; export interface SelectedHeadingBugProps { bus: ArincEventBus, @@ -68,7 +70,7 @@ export class SelectedHeadingBug extends DisplayComponent(); + const sub = this.props.bus.getArincSubscriber(); sub.on('selectedHeading').whenChanged().handle((v) => { this.selected.set(v); @@ -84,7 +86,7 @@ export class SelectedHeadingBug extends DisplayComponent @@ -115,7 +117,7 @@ export class SelectedHeadingBug extends DisplayComponent `rotate(${(diff) < 0 ? -38 : 38} 384 620)`)} - class="shadow Cyan" + class="Cyan shadow" font-size={22} > {this.selected.map((selected) => ( diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/index.tsx b/fbw-common/src/systems/instruments/src/ND/pages/arc/index.tsx similarity index 88% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/arc/index.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/arc/index.tsx index 1cedb555b09..f66822f9948 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/arc/index.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/arc/index.tsx @@ -3,18 +3,15 @@ // SPDX-License-Identifier: GPL-3.0 import { FSComponent, ComponentProps, ConsumerSubject, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, rangeSettings } from '@shared/NavigationDisplay'; -import { LsCourseBug } from 'instruments/src/ND/pages/arc/LsCourseBug'; -import { ArincEventBus } from 'instruments/src/MsfsAvionicsCommon/ArincEventBus'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; +import { ArincEventBus, Arinc429WordData, Arinc429RegisterSubject, EfisNdMode, efisRangeSettings, MathUtils } from '@flybywiresim/fbw-sdk'; + +import { LsCourseBug } from './LsCourseBug'; import { ArcModeUnderlay } from './ArcModeUnderlay'; -import { getSmallestAngle } from '../../../PFD/PFDUtils'; import { Flag } from '../../shared/Flag'; import { NDPage } from '../NDPage'; import { NDControlEvents } from '../../NDControlEvents'; -import { AdirsSimVars } from '../../../MsfsAvionicsCommon/SimVarTypes'; -import { Arinc429RegisterSubject } from '../../../MsfsAvionicsCommon/Arinc429RegisterSubject'; +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; +import { GenericAdirsEvents } from '../../types/GenericAdirsEvents'; export interface ArcModePageProps extends ComponentProps { bus: ArincEventBus, @@ -34,7 +31,7 @@ export class ArcModePage extends NDPage { private readonly pposLonWord = Arinc429RegisterSubject.createEmpty(); - private readonly mapRangeSub = ConsumerSubject.create(this.props.bus.getSubscriber().on('ndRangeSetting').whenChanged(), -1); + private readonly mapRangeSub = ConsumerSubject.create(this.props.bus.getSubscriber().on('ndRangeSetting').whenChanged(), -1); private readonly ringAvailable = MappedSubject.create(([isUsingTrackUpMode, headingWord, trackWord]) => { if (isUsingTrackUpMode) { @@ -49,7 +46,7 @@ export class ArcModePage extends NDPage { private readonly planeRotation = MappedSubject.create(([isUsingTrackUpMode, headingWord, trackWord]) => { if (isUsingTrackUpMode) { if (headingWord.isNormalOperation() && trackWord.isNormalOperation()) { - return getSmallestAngle(headingWord.value, trackWord.value); + return MathUtils.getSmallestAngle(headingWord.value, trackWord.value); } } @@ -74,7 +71,7 @@ export class ArcModePage extends NDPage { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('latitude').whenChanged().handle((v) => this.pposLatWord.setWord(v)); sub.on('longitude').whenChanged().handle((v) => this.pposLonWord.setWord(v)); @@ -176,7 +173,7 @@ export class ArcModePage extends NDPage { publisher.pub('set_map_efis_mode', EfisNdMode.ARC); publisher.pub('set_map_pixel_radius', 498); - publisher.pub('set_map_range_radius', rangeSettings[this.mapRangeSub.get()]); + publisher.pub('set_map_range_radius', efisRangeSettings[this.mapRangeSub.get()]); publisher.pub('set_map_center_y_bias', 242); } diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/plan/PlanModeUnderlay.tsx b/fbw-common/src/systems/instruments/src/ND/pages/plan/PlanModeUnderlay.tsx similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/plan/PlanModeUnderlay.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/plan/PlanModeUnderlay.tsx diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/plan/index.tsx b/fbw-common/src/systems/instruments/src/ND/pages/plan/index.tsx similarity index 92% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/plan/index.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/plan/index.tsx index 7ed541901fd..678d56de5bc 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/plan/index.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/plan/index.tsx @@ -3,15 +3,15 @@ // SPDX-License-Identifier: GPL-3.0 import { FSComponent, ComponentProps, Subscribable, VNode, Subject, EventBus, ConsumerSubject } from '@microsoft/msfs-sdk'; -import { Arinc429Register, Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { EfisNdMode, rangeSettings } from '@shared/NavigationDisplay'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; +import { Arinc429Register, Arinc429WordData, EfisNdMode, efisRangeSettings } from '@flybywiresim/fbw-sdk'; + import { PlanModeUnderlay } from './PlanModeUnderlay'; import { MapParameters } from '../../shared/utils/MapParameters'; import { NDPage } from '../NDPage'; import { NDControlEvents } from '../../NDControlEvents'; import { NDSimvars } from '../../NDSimvarPublisher'; -import { AdirsSimVars } from '../../../MsfsAvionicsCommon/SimVarTypes'; +import { GenericAdirsEvents } from '../../types/GenericAdirsEvents'; +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; export interface PlanModePageProps extends ComponentProps { bus: EventBus, @@ -23,7 +23,7 @@ export class PlanModePage extends NDPage { private readonly controlPublisher = this.props.bus.getPublisher(); - private readonly subs = this.props.bus.getSubscriber(); + private readonly subs = this.props.bus.getSubscriber(); private readonly pposLatSub = ConsumerSubject.create(this.subs.on('latitude').whenChanged(), -1); @@ -43,7 +43,7 @@ export class PlanModePage extends NDPage { private readonly selectedWaypointLongSub = ConsumerSubject.create(this.subs.on('selectedWaypointLong').whenChanged(), -1); - private readonly mapRangeSub = ConsumerSubject.create(this.props.bus.getSubscriber().on('ndRangeSetting').whenChanged(), -1); + private readonly mapRangeSub = ConsumerSubject.create(this.props.bus.getSubscriber().on('ndRangeSetting').whenChanged(), -1); private readonly mapParams = new MapParameters(); @@ -125,7 +125,7 @@ export class PlanModePage extends NDPage { private handleScaleMap() { if (this.isVisible.get()) { const rangeSetting = this.mapRangeSub.get(); - const range = rangeSettings[rangeSetting]; + const range = efisRangeSettings[rangeSetting]; this.controlPublisher.pub('set_map_efis_mode', EfisNdMode.PLAN); this.controlPublisher.pub('set_map_pixel_radius', 250); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx similarity index 90% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx index 7fda555022d..02840ec1202 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/Glideslope.tsx @@ -1,6 +1,6 @@ import { FSComponent, ComponentProps, DisplayComponent, VNode, Subject, EventBus, MappedSubject } from '@microsoft/msfs-sdk'; -import { Layer } from '../../../MsfsAvionicsCommon/Layer'; -import { VorSimVars } from '../../../MsfsAvionicsCommon/providers/VorBusPublisher'; +import { GenericVorEvents } from '../../types/GenericVorEvents'; +import { Layer } from '../../Layer'; export interface GlideSlopeProps extends ComponentProps { bus: EventBus, @@ -26,7 +26,7 @@ export class GlideSlope extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const subs = this.props.bus.getSubscriber(); + const subs = this.props.bus.getSubscriber(); // TODO select correct MMR @@ -56,14 +56,14 @@ export class GlideSlope extends DisplayComponent { `translate(0 ${Math.max(-128, deviationPx)})`)} - class="rounded Magenta" + class="Magenta rounded" stroke-width={2.5} visibility={this.deviationUpperVisibleSub.map(this.visibilityFn)} /> `translate(0 ${Math.min(128, deviationPx)})`)} - class="rounded Magenta" + class="Magenta rounded" stroke-width={2.5} visibility={this.deviationLowerVisibleSub.map(this.visibilityFn)} /> diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx similarity index 91% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx index df5e3ee05c8..1b6774d5c03 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/IlsInfoIndicator.tsx @@ -1,8 +1,13 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, VNode, Subject, EventBus, ConsumerSubject, MappedSubject } from '@microsoft/msfs-sdk'; -import { FMBusEvents } from 'instruments/src/MsfsAvionicsCommon/providers/FMBusPublisher'; -import { Arinc429RegisterSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject'; -import { Layer } from '../../../MsfsAvionicsCommon/Layer'; -import { VorSimVars } from '../../../MsfsAvionicsCommon/providers/VorBusPublisher'; +import { Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; + +import { GenericVorEvents } from '../../types/GenericVorEvents'; +import { GenericFlightManagementBusEvents } from '../../types/GenericFlightManagementBusEvents'; +import { Layer } from '../../Layer'; export interface IlsInfoIndicatorProps { bus: EventBus, @@ -51,7 +56,7 @@ export class IlsInfoIndicator extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const subs = this.props.bus.getSubscriber(); + const subs = this.props.bus.getSubscriber(); // TODO select correct MMR // Fixed now?? diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx similarity index 93% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx index de94d291f16..21c69097a06 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseLSPage.tsx @@ -4,14 +4,15 @@ import { ComponentProps, DisplayComponent, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; import { Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { VorSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/VorBusPublisher'; -import { AdirsSimVars } from 'instruments/src/MsfsAvionicsCommon/SimVarTypes'; + import { RoseMode, RoseModeProps } from './RoseMode'; import { RoseModeUnderlay } from './RoseModeUnderlay'; import { NDControlEvents } from '../../NDControlEvents'; import { IlsInfoIndicator } from './IlsInfoIndicator'; import { GlideSlope } from './Glideslope'; +import { GenericAdirsEvents } from '../../types/GenericAdirsEvents'; +import { GenericDisplayManagementEvents } from '../../types/GenericDisplayManagementEvents'; +import { GenericVorEvents } from '../../types/GenericVorEvents'; export interface RoseLsProps extends RoseModeProps { index: 1 | 2, @@ -37,7 +38,7 @@ export class RoseLSPage extends RoseMode { const publisher = this.props.bus.getPublisher(); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); const index: 3 | 4 = this.props.index + 2 as (3|4); @@ -143,7 +144,7 @@ class IlsCaptureOverlay extends DisplayComponent { /> @@ -159,7 +160,7 @@ class IlsCaptureOverlay extends DisplayComponent { /> `translate(${cdiPx}, 0)`)} id="ils-deviation" stroke-width={4} diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx similarity index 77% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx index 8c095b0b658..bedcc800ddd 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseMode.tsx @@ -2,10 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0 -import { FSComponent, ComponentProps, Subscribable, Subject } from '@microsoft/msfs-sdk'; -import { Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { EfisNdRangeValue } from '@shared/NavigationDisplay'; -import { ArincEventBus } from 'instruments/src/MsfsAvionicsCommon/ArincEventBus'; +import { ComponentProps, Subscribable, Subject } from '@microsoft/msfs-sdk'; +import { ArincEventBus, Arinc429WordData, EfisNdRangeValue } from '@flybywiresim/fbw-sdk'; + import { NDPage } from '../NDPage'; import { NDControlEvents } from '../../NDControlEvents'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx similarity index 92% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx index 5d33bb98afe..ed063df4e6d 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseModeUnderlay.tsx @@ -3,10 +3,10 @@ // SPDX-License-Identifier: GPL-3.0 import { FSComponent, DisplayComponent, ComponentProps, Subject, Subscribable, VNode, EventBus } from '@microsoft/msfs-sdk'; -import { Arinc429WordData, MathUtils } from '@flybywiresim/fbw-sdk'; -import { rangeSettings } from '@shared/NavigationDisplay'; -import { TcasSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/TcasBusPublisher'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; +import { Arinc429WordData, MathUtils, efisRangeSettings } from '@flybywiresim/fbw-sdk'; + +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; +import { GenericTcasEvents } from '../../types/GenericTcasEvents'; export interface RoseModeOverlayProps { bus: EventBus, @@ -46,10 +46,10 @@ export class RoseModeUnderlay extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('ndRangeSetting').whenChanged().handle((value) => { - this.rangeValue.set(rangeSettings[value]); + this.rangeValue.set(efisRangeSettings[value]); this.handleRingVisibilities(); }); @@ -92,34 +92,34 @@ export class RoseModeUnderlay extends DisplayComponent { {/* middle range ring replaced with tcas range ticks */} - - - - - - - - - - - - + + + + + + + + + + + + {/* R = 62, tcas range ticks */} - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx similarity index 85% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx index 3947eff0387..e3b492bdacc 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseNavPage.tsx @@ -1,21 +1,24 @@ -import { ConsumerSubject, FSComponent, MappedSubject, Subject, VNode } from '@microsoft/msfs-sdk'; -import { EfisNdMode, rangeSettings } from '@shared/NavigationDisplay'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { LsCourseBug } from 'instruments/src/ND/pages/arc/LsCourseBug'; -import { getSmallestAngle } from 'instruments/src/PFD/PFDUtils'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { FSComponent, ConsumerSubject, MappedSubject, Subject, VNode } from '@microsoft/msfs-sdk'; +import { Arinc429RegisterSubject, EfisNdMode, efisRangeSettings, MathUtils } from '@flybywiresim/fbw-sdk'; + +import { LsCourseBug } from '../arc/LsCourseBug'; import { Flag } from '../../shared/Flag'; import { RoseMode } from './RoseMode'; import { RoseModeUnderlay } from './RoseModeUnderlay'; -import { Arinc429RegisterSubject } from '../../../MsfsAvionicsCommon/Arinc429RegisterSubject'; -import { AdirsSimVars } from '../../../MsfsAvionicsCommon/SimVarTypes'; import { NDControlEvents } from '../../NDControlEvents'; +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; +import { GenericAdirsEvents } from '../../types/GenericAdirsEvents'; export class RoseNavPage extends RoseMode { private readonly pposLatWord = Arinc429RegisterSubject.createEmpty(); private readonly pposLonWord = Arinc429RegisterSubject.createEmpty(); - private readonly mapRangeSub = ConsumerSubject.create(this.props.bus.getSubscriber().on('ndRangeSetting').whenChanged(), -1); + private readonly mapRangeSub = ConsumerSubject.create(this.props.bus.getSubscriber().on('ndRangeSetting').whenChanged(), -1); private readonly mapFlagShown = MappedSubject.create(([headingWord, latWord, longWord]) => { return !headingWord.isNormalOperation() || !latWord.isNormalOperation() || !longWord.isNormalOperation(); @@ -24,7 +27,7 @@ export class RoseNavPage extends RoseMode { private readonly planeRotation = MappedSubject.create(([isUsingTrackUpMode, headingWord, trackWord]) => { if (isUsingTrackUpMode) { if (headingWord.isNormalOperation() && trackWord.isNormalOperation()) { - return getSmallestAngle(headingWord.value, trackWord.value); + return MathUtils.getSmallestAngle(headingWord.value, trackWord.value); } } @@ -43,7 +46,7 @@ export class RoseNavPage extends RoseMode { } }); - const sub = this.props.bus.getArincSubscriber(); + const sub = this.props.bus.getArincSubscriber(); sub.on('latitude').whenChanged().handle((v) => this.pposLatWord.setWord(v)); sub.on('longitude').whenChanged().handle((v) => this.pposLonWord.setWord(v)); @@ -109,7 +112,7 @@ export class RoseNavPage extends RoseMode { const publisher = this.props.bus.getPublisher(); const rangeSetting = this.mapRangeSub.get(); - const range = rangeSettings[rangeSetting]; + const range = efisRangeSettings[rangeSetting]; publisher.pub('set_map_efis_mode', EfisNdMode.ROSE_NAV); publisher.pub('set_map_pixel_radius', 250); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx similarity index 94% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx index 7bfd0a99e3f..0786969853f 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/RoseVorPage.tsx @@ -3,16 +3,16 @@ // SPDX-License-Identifier: GPL-3.0 import { FSComponent, DisplayComponent, ComponentProps, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; +import { Arinc429WordData, Arinc429ConsumerSubject } from '@flybywiresim/fbw-sdk'; + import { RoseMode, RoseModeProps } from './RoseMode'; import { RoseModeUnderlay } from './RoseModeUnderlay'; -import { VorSimVars } from '../../../MsfsAvionicsCommon/providers/VorBusPublisher'; -import { AdirsSimVars } from '../../../MsfsAvionicsCommon/SimVarTypes'; import { Flag } from '../../shared/Flag'; import { NDControlEvents } from '../../NDControlEvents'; import { VorInfoIndicator } from './VorInfoIndicator'; -import { Arinc429ConsumerSubject } from '../../../MsfsAvionicsCommon/Arinc429ConsumerSubject'; +import { GenericAdirsEvents } from '../../types/GenericAdirsEvents'; +import { GenericDisplayManagementEvents } from '../../types/GenericDisplayManagementEvents'; +import { GenericVorEvents } from '../../types/GenericVorEvents'; export interface RoseVorProps extends RoseModeProps { index: 1 | 2, @@ -42,7 +42,7 @@ export class RoseVorPage extends RoseMode { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); const index = this.props.index; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx b/fbw-common/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx similarity index 91% rename from fbw-a32nx/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx rename to fbw-common/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx index ed60e1262b1..2046c53148c 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx +++ b/fbw-common/src/systems/instruments/src/ND/pages/rose/VorInfoIndicator.tsx @@ -1,8 +1,13 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, ComponentProps, DisplayComponent, EventBus, Subject, VNode, MappedSubject } from '@microsoft/msfs-sdk'; -import { Layer } from 'instruments/src/MsfsAvionicsCommon/Layer'; -import { VorSimVars } from '../../../MsfsAvionicsCommon/providers/VorBusPublisher'; -import { FMBusEvents } from '../../../MsfsAvionicsCommon/providers/FMBusPublisher'; -import { Arinc429RegisterSubject } from '../../../MsfsAvionicsCommon/Arinc429RegisterSubject'; +import { Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; + +import { GenericVorEvents } from '../../types/GenericVorEvents'; +import { GenericFlightManagementBusEvents } from '../../types/GenericFlightManagementBusEvents'; +import { Layer } from '../../Layer'; export interface VorInfoIndicatorProps extends ComponentProps { bus: EventBus, @@ -51,7 +56,7 @@ export class VorInfoIndicator extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const subs = this.props.bus.getSubscriber(); + const subs = this.props.bus.getSubscriber(); subs.on(`nav${this.props.index}Ident`).whenChanged().handle((value) => { this.vorIdent.set(value); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/Airplane.tsx b/fbw-common/src/systems/instruments/src/ND/shared/Airplane.tsx similarity index 87% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/Airplane.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/Airplane.tsx index 322d81be249..34555828fac 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/Airplane.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/Airplane.tsx @@ -1,11 +1,15 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, VNode, Subject, EventBus, MappedSubject, Subscribable } from '@microsoft/msfs-sdk'; -import { EfisNdMode } from '@shared/NavigationDisplay'; -import { DmcEvents } from '../../MsfsAvionicsCommon/providers/DmcPublisher'; -import { Layer } from '../../MsfsAvionicsCommon/Layer'; -import { AdirsSimVars } from '../../MsfsAvionicsCommon/SimVarTypes'; +import { EfisNdMode, Arinc429ConsumerSubject } from '@flybywiresim/fbw-sdk'; + import { NDControlEvents } from '../NDControlEvents'; -import { Arinc429ConsumerSubject } from '../../MsfsAvionicsCommon/Arinc429ConsumerSubject'; import { LubberLine } from '../pages/arc/LubberLine'; +import { GenericAdirsEvents } from '../types/GenericAdirsEvents'; +import { GenericDisplayManagementEvents } from '../types/GenericDisplayManagementEvents'; +import { Layer } from '../Layer'; const PLANE_X_OFFSET = -41; const PLANE_Y_OFFSET = 0; @@ -36,7 +40,7 @@ export class Airplane extends DisplayComponent<{ bus: EventBus, ndMode: Subscrib onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); this.headingWord.setConsumer(sub.on('heading')); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/CrossTrackError.tsx b/fbw-common/src/systems/instruments/src/ND/shared/CrossTrackError.tsx similarity index 91% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/CrossTrackError.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/CrossTrackError.tsx index 68e03defc65..47357a7a4b2 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/CrossTrackError.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/CrossTrackError.tsx @@ -1,6 +1,11 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, Subject, Subscribable, VNode, EventBus, MappedSubject } from '@microsoft/msfs-sdk'; -import { EfisNdMode } from '@shared/NavigationDisplay'; -import { FmsVars } from '../../MsfsAvionicsCommon/providers/FmsDataPublisher'; +import { EfisNdMode } from '@flybywiresim/fbw-sdk'; + +import { GenericFmsEvents } from '../types/GenericFmsEvents'; export interface CrossTrackErrorProps { bus: EventBus, @@ -42,7 +47,7 @@ export class CrossTrackError extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('crossTrackError').atFrequency(2).handle((crossTrackError) => { const x = this.xValueInitial.get(); @@ -87,7 +92,7 @@ export class CrossTrackError extends DisplayComponent { y={this.yValueInitial} text-anchor={MappedSubject.create(([currentPageMode, crossTrackAnchor]) => (currentPageMode === EfisNdMode.PLAN ? 'start' : crossTrackAnchor), this.props.currentPageMode, this.crossTrackAnchor)} - class="shadow Green FontSmall" + class="Green FontSmall shadow" visibility={this.crossTrackVisibility} > {this.crossTrackText} diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/Flag.tsx b/fbw-common/src/systems/instruments/src/ND/shared/Flag.tsx similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/Flag.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/Flag.tsx diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx b/fbw-common/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx similarity index 94% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx index f34a09e0ed5..83bd3d71270 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/RadioNavInfo.tsx @@ -1,11 +1,15 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, EventBus, MappedSubject, Subject, Subscribable, VNode, DebounceTimer } from '@microsoft/msfs-sdk'; -import { VorSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/VorBusPublisher'; -import { EfisNdMode, NavAidMode } from '@shared/NavigationDisplay'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { Layer } from 'instruments/src/MsfsAvionicsCommon/Layer'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { Arinc429RegisterSubject } from '../../MsfsAvionicsCommon/Arinc429RegisterSubject'; -import { FMBusEvents } from '../../MsfsAvionicsCommon/providers/FMBusPublisher'; +import { Arinc429RegisterSubject, EfisNdMode, NavAidMode } from '@flybywiresim/fbw-sdk'; + +import { GenericFcuEvents } from '../types/GenericFcuEvents'; +import { GenericDisplayManagementEvents } from '../types/GenericDisplayManagementEvents'; +import { GenericVorEvents } from '../types/GenericVorEvents'; +import { Layer } from '../Layer'; +import { GenericFlightManagementBusEvents } from '../types/GenericFlightManagementBusEvents'; export class RadioNavInfo extends DisplayComponent<{ bus: EventBus, index: 1 | 2, mode: Subscribable }> { private readonly isVor = Subject.create(true); @@ -15,7 +19,7 @@ export class RadioNavInfo extends DisplayComponent<{ bus: EventBus, index: 1 | 2 onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on(`navaidMode${this.props.index}`).whenChanged().handle((value) => { if (value === NavAidMode.VOR) { @@ -120,7 +124,7 @@ class VorInfo extends DisplayComponent<{ bus: EventBus, index: 1 | 2, visible: S onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on(`nav${this.props.index}Ident`).whenChanged().handle((v) => this.identSub.set(v)); sub.on(`nav${this.props.index}Frequency`).whenChanged().handle((v) => this.frequencySub.set(v)); @@ -230,7 +234,7 @@ class AdfInfo extends DisplayComponent<{ bus: EventBus, index: 1 | 2, visible: S onAfterRender(node: VNode) { super.onAfterRender(node); - const subs = this.props.bus.getSubscriber(); + const subs = this.props.bus.getSubscriber(); subs.on(`adf${this.props.index}Ident`).whenChanged().handle((value) => this.adfIdent.set(value)); subs.on(`adf${this.props.index}ActiveFrequency`).whenChanged().handle((value) => this.adfFrequency.set(value)); @@ -356,7 +360,7 @@ class TuningModeIndicator extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const subs = this.props.bus.getSubscriber(); + const subs = this.props.bus.getSubscriber(); subs.on('fm.1.healthy_discrete').whenChanged().handle((healthy) => this.fm1Healthy.set(healthy)); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/RadioNeedle.tsx b/fbw-common/src/systems/instruments/src/ND/shared/RadioNeedle.tsx similarity index 92% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/RadioNeedle.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/RadioNeedle.tsx index 009c069dbdc..cc2c5451fbd 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/RadioNeedle.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/RadioNeedle.tsx @@ -3,14 +3,13 @@ // SPDX-License-Identifier: GPL-3.0 import { FSComponent, DisplayComponent, EventBus, Subject, Subscribable, VNode, MappedSubject, ClockEvents } from '@microsoft/msfs-sdk'; -import { EfisNdMode, NavAidMode } from '@shared/NavigationDisplay'; -import { Arinc429WordData } from '@flybywiresim/fbw-sdk'; -import { getSmallestAngle } from 'instruments/src/PFD/PFDUtils'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; +import { EfisNdMode, MathUtils, NavAidMode, Arinc429WordData } from '@flybywiresim/fbw-sdk'; + import { diffAngle } from 'msfs-geo'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { VorSimVars } from '../../MsfsAvionicsCommon/providers/VorBusPublisher'; -import { AdirsSimVars } from '../../MsfsAvionicsCommon/SimVarTypes'; +import { GenericFcuEvents } from '../types/GenericFcuEvents'; +import { GenericAdirsEvents } from '../types/GenericAdirsEvents'; +import { GenericDisplayManagementEvents } from '../types/GenericDisplayManagementEvents'; +import { GenericVorEvents } from '../types/GenericVorEvents'; export interface RadioNeedleProps { bus: EventBus, @@ -29,7 +28,7 @@ export class RadioNeedle extends DisplayComponent { private readonly trackCorrection = MappedSubject.create(([isUsingTrackUpMode, headingWord, trackWord]) => { if (isUsingTrackUpMode) { if (headingWord.isNormalOperation() && trackWord.isNormalOperation()) { - return getSmallestAngle(headingWord.value, trackWord.value); + return MathUtils.getSmallestAngle(headingWord.value, trackWord.value); } } @@ -39,7 +38,7 @@ export class RadioNeedle extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on(`navaidMode${this.props.index}`).whenChanged().handle((mode) => { if (mode === NavAidMode.VOR) { @@ -146,7 +145,7 @@ class VorNeedle extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on(`nav${this.props.index}RelativeBearing`).whenChanged().handle((value) => this.rawRelativeBearing.set(value)); sub.on(`nav${this.props.index}Available`).whenChanged().handle((value) => this.radioAvailable.set(!!value)); @@ -236,7 +235,7 @@ class AdfNeedle extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on(`adf${this.props.index}Radial`).whenChanged().handle((value) => this.relativeBearing.set(value)); sub.on(`adf${this.props.index}SignalStrength`).whenChangedBy(1).handle((value) => this.radioAvailable.set(value > 0)); @@ -270,7 +269,7 @@ class AdfNeedle extends DisplayComponent { arr[this.props.index - 1])} stroke-width={3.2} - class="rounded Green" + class="Green rounded" /> ); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/TrackBug.tsx b/fbw-common/src/systems/instruments/src/ND/shared/TrackBug.tsx similarity index 78% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/TrackBug.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/TrackBug.tsx index 6c889f4fd06..008cdfc943f 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/TrackBug.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/TrackBug.tsx @@ -1,19 +1,13 @@ -import { - ConsumerSubject, - DisplayComponent, - EventBus, - FSComponent, - MappedSubject, - Subject, - Subscribable, - VNode, -} from '@microsoft/msfs-sdk'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { EfisNdMode } from '@shared/NavigationDisplay'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { ConsumerSubject, DisplayComponent, EventBus, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; +import { EfisNdMode, Arinc429ConsumerSubject, MathUtils } from '@flybywiresim/fbw-sdk'; + import { NDSimvars } from '../NDSimvarPublisher'; -import { getSmallestAngle } from '../../PFD/PFDUtils'; -import { Arinc429ConsumerSubject } from '../../MsfsAvionicsCommon/Arinc429ConsumerSubject'; -import { FcuSimVars } from '../../MsfsAvionicsCommon/providers/FcuBusPublisher'; +import { GenericDisplayManagementEvents } from '../types/GenericDisplayManagementEvents'; +import { GenericFcuEvents } from '../types/GenericFcuEvents'; export interface TrackBugProps { bus: EventBus, @@ -39,7 +33,7 @@ export class TrackBug extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); this.ndMode.setConsumer(sub.on('ndMode').whenChanged()); this.headingWord.setConsumer(sub.on('heading')); @@ -63,7 +57,7 @@ export class TrackBug extends DisplayComponent { if (this.props.isUsingTrackUpMode.get()) { diff = 0; } else { - diff = getSmallestAngle(this.trackWord.get().value, this.headingWord.get().value); + diff = MathUtils.getSmallestAngle(this.trackWord.get().value, this.headingWord.get().value); } this.bugShown.set(diff <= 40); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/TrackLine.tsx b/fbw-common/src/systems/instruments/src/ND/shared/TrackLine.tsx similarity index 83% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/TrackLine.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/TrackLine.tsx index d0d7a0993a4..67b93a7d6b0 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/TrackLine.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/TrackLine.tsx @@ -3,14 +3,12 @@ // SPDX-License-Identifier: GPL-3.0 import { FSComponent, DisplayComponent, EventBus, VNode, MappedSubject, Subscribable, ConsumerSubject, Subject } from '@microsoft/msfs-sdk'; -import { MathUtils } from '@flybywiresim/fbw-sdk'; -import { ArmedLateralMode, isArmed, LateralMode } from '@shared/autopilot'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { EfisNdMode } from '@shared/NavigationDisplay'; +import { MathUtils, EfisNdMode, Arinc429ConsumerSubject } from '@flybywiresim/fbw-sdk'; + import { NDSimvars } from '../NDSimvarPublisher'; -import { FGVars } from '../../MsfsAvionicsCommon/providers/FGDataPublisher'; -import { FcuSimVars } from '../../MsfsAvionicsCommon/providers/FcuBusPublisher'; -import { Arinc429ConsumerSubject } from '../../MsfsAvionicsCommon/Arinc429ConsumerSubject'; +import { GenericDisplayManagementEvents } from '../types/GenericDisplayManagementEvents'; +import { GenericFcuEvents } from '../types/GenericFcuEvents'; +import { ArmedLateralMode, GenericFlightGuidanceEvents, LateralMode, isArmed } from '../types/GenericFlightGuidanceEvents'; export interface TrackLineProps { bus: EventBus, @@ -25,7 +23,7 @@ const TRACK_LINE_Y_POSITION = { export class TrackLine extends DisplayComponent { private readonly lineRef = FSComponent.createRef(); - private readonly sub = this.props.bus.getSubscriber(); + private readonly sub = this.props.bus.getSubscriber(); private readonly ndMode = ConsumerSubject.create(this.sub.on('ndMode').whenChanged(), EfisNdMode.ARC); @@ -93,7 +91,7 @@ export class TrackLine extends DisplayComponent { return ( - + ); } diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/WindIndicator.tsx b/fbw-common/src/systems/instruments/src/ND/shared/WindIndicator.tsx similarity index 90% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/WindIndicator.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/WindIndicator.tsx index 639ce667d2a..447b8a3c914 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/WindIndicator.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/WindIndicator.tsx @@ -1,8 +1,13 @@ +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + import { FSComponent, DisplayComponent, EventBus, Subject, VNode } from '@microsoft/msfs-sdk'; -import { DmcLogicEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; -import { Arinc429RegisterSubject } from '../../MsfsAvionicsCommon/Arinc429RegisterSubject'; -import { AdirsSimVars } from '../../MsfsAvionicsCommon/SimVarTypes'; -import { Layer } from '../../MsfsAvionicsCommon/Layer'; +import { Arinc429RegisterSubject } from '@flybywiresim/fbw-sdk'; + +import { GenericAdirsEvents } from '../types/GenericAdirsEvents'; +import { GenericDisplayManagementEvents } from '../types/GenericDisplayManagementEvents'; +import { Layer } from '../Layer'; const mod = (x: number, n: number) => x - Math.floor(x / n) * n; @@ -24,7 +29,7 @@ export class WindIndicator extends DisplayComponent<{ bus: EventBus }> { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('windDirection').atFrequency(2).handle((value) => { this.windDirectionWord.setWord(value); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/common.scss b/fbw-common/src/systems/instruments/src/ND/shared/common.scss similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/common.scss rename to fbw-common/src/systems/instruments/src/ND/shared/common.scss diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx b/fbw-common/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx similarity index 94% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx rename to fbw-common/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx index b84c62311b1..47eba2b1cc8 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/CanvasMap.tsx @@ -2,14 +2,10 @@ // // SPDX-License-Identifier: GPL-3.0 -/* eslint-disable max-len */ import { BitFlags, ClockEvents, DisplayComponent, EventBus, FSComponent, MappedSubject, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk'; -import { EfisNdMode, EfisVectorsGroup, NdSymbol, NdSymbolTypeFlags, NdTraffic } from '@shared/NavigationDisplay'; -import type { PathVector } from '@fmgc/guidance/lnav/PathVector'; +import { EfisNdMode, EfisVectorsGroup, NdSymbol, NdSymbolTypeFlags, NdTraffic, MathUtils, PathVector } from '@flybywiresim/fbw-sdk'; + import { Coordinates, distanceTo } from 'msfs-geo'; -import { TaRaIntrusion } from '@tcas/lib/TcasConstants'; -import { MathUtils } from '@flybywiresim/fbw-sdk'; -import { FcuSimVars } from 'instruments/src/MsfsAvionicsCommon/providers/FcuBusPublisher'; import { FmsSymbolsData } from '../../FmsSymbolsPublisher'; import { MapParameters } from '../utils/MapParameters'; import { NDSimvars } from '../../NDSimvarPublisher'; @@ -20,6 +16,10 @@ import { TrafficLayer } from './TrafficLayer'; import { FixInfoLayer } from './FixInfoLayer'; import { NDControlEvents } from '../../NDControlEvents'; import { PseudoWaypointLayer } from './PseudoWaypointLayer'; +import { GenericFcuEvents } from '../../types/GenericFcuEvents'; + +// TODO move this somewhere better, need to move TCAS stuff into fbw-sdk +declare enum TaRaIntrusion { TRAFFIC = 0, PROXIMITY = 1, TA = 2, RA = 3 } const ARC_CLIP = new Path2D('M0,312 a492,492 0 0 1 768,0 L768,562 L648,562 L591,625 L591,768 L174,768 L174,683 L122,625 L0,625 L0,312'); @@ -100,7 +100,7 @@ export class CanvasMap extends DisplayComponent { onAfterRender(node: VNode) { super.onAfterRender(node); - const sub = this.props.bus.getSubscriber(); + const sub = this.props.bus.getSubscriber(); sub.on('set_show_map').handle((show) => this.mapVisible.set(show)); sub.on('set_map_recomputing').handle((show) => this.mapRecomputing.set(show)); @@ -419,11 +419,15 @@ export class CanvasMap extends DisplayComponent { width={768} height={768} class="nd-canvas-map" - style={MappedSubject.create(([r, x, y]) => `width: ${r}px; height: ${r}px; position: absolute; top: 0; left: 0; transform: translate(${-(r / 2) + x}px, ${-(r / 2) + y}px)`, Subject.create(768), this.props.x, this.props.y)} + style={MappedSubject.create(([r, x, y]) => { + return `width: ${r}px; height: ${r}px; position: absolute; top: 0; left: 0; transform: translate(${-(r / 2) + x}px, ${-(r / 2) + y}px)`; + }, Subject.create(768), this.props.x, this.props.y)} />

`width: ${r}px; height: ${r}px; position: absolute; top: 0; left: 0; transform: translate(${-(r / 2) + x}px, ${-(r / 2) + y}px)`, Subject.create(768), this.props.x, this.props.y)} + style={MappedSubject.create(([r, x, y]) => { + return `width: ${r}px; height: ${r}px; position: absolute; top: 0; left: 0; transform: translate(${-(r / 2) + x}px, ${-(r / 2) + y}px)`; + }, Subject.create(768), this.props.x, this.props.y)} /> ); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts similarity index 92% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts index d43546b9f05..4d98539d4df 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/ConstraintsLayer.ts @@ -1,4 +1,9 @@ -import { NdSymbol, NdSymbolTypeFlags } from '@shared/NavigationDisplay'; +// Copyright (c) 2021-2023 FlyByWire Simulations +// +// SPDX-License-Identifier: GPL-3.0 + +import { NdSymbol, NdSymbolTypeFlags } from '@flybywiresim/fbw-sdk'; + import { MapLayer } from './MapLayer'; import { MapParameters } from '../utils/MapParameters'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts similarity index 96% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts index eae8d7bae3e..068085ace12 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/FixInfoLayer.ts @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0 -import { NdSymbol } from '@shared/NavigationDisplay'; -import { MathUtils } from '@flybywiresim/fbw-sdk'; +import { NdSymbol, MathUtils } from '@flybywiresim/fbw-sdk'; + import { MapLayer } from './MapLayer'; import { MapParameters } from '../utils/MapParameters'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/MapLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/MapLayer.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/MapLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/MapLayer.ts diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/PaintUtils.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/PaintUtils.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/PaintUtils.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/PaintUtils.ts diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts similarity index 94% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts index e85b5b39074..d211970c37e 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/PseudoWaypointLayer.ts @@ -2,15 +2,14 @@ // // SPDX-License-Identifier: GPL-3.0 -import { NdSymbol, NdSymbolTypeFlags } from '@shared/NavigationDisplay'; import { EventBus } from '@microsoft/msfs-sdk'; +import { NdSymbol, NdSymbolTypeFlags, Arinc429ConsumerSubject, Arinc429Register, MathUtils } from '@flybywiresim/fbw-sdk'; + import { NDSimvars } from 'instruments/src/ND/NDSimvarPublisher'; -import { Arinc429ConsumerSubject } from 'instruments/src/MsfsAvionicsCommon/Arinc429ConsumerSubject'; -import { Arinc429Register, MathUtils } from '@flybywiresim/fbw-sdk'; -import { DmcEvents } from 'instruments/src/MsfsAvionicsCommon/providers/DmcPublisher'; import { MapLayer } from './MapLayer'; import { MapParameters } from '../utils/MapParameters'; import { PaintUtils } from './PaintUtils'; +import { GenericDisplayManagementEvents } from '../../types/GenericDisplayManagementEvents'; // eslint-disable-next-line max-len const DECEL_PATH = new Path2D('m 14.5125 0 c 0 8.015 -6.4975 14.5125 -14.5125 14.5125 c -8.015 0 -14.5125 -6.4975 -14.5125 -14.5125 c 0 -8.015 6.4975 -14.5125 14.5125 -14.5125 c 8.015 0 14.5125 6.4975 14.5125 14.5125 z m -12.15 -9.7875 h -7.7625 v 18.225 h 7.7625 l 2.7 -3.375 v -11.475 l -2.7 -3.375 z'); @@ -32,7 +31,7 @@ export class PseudoWaypointLayer implements MapLayer { private trackWord = Arinc429ConsumerSubject.create(null); constructor(readonly bus: EventBus) { - const sub = this.bus.getSubscriber(); + const sub = this.bus.getSubscriber(); sub.on('groundSpeed').handle((s) => this.groundSpeed.set(s)); diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts similarity index 97% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts index db58c6d8be5..b7ab221048d 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/RunwayLayer.ts @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0 -import { NdSymbol, NdSymbolTypeFlags } from '@shared/NavigationDisplay'; -import { MathUtils } from '@flybywiresim/fbw-sdk'; +import { NdSymbol, NdSymbolTypeFlags, MathUtils } from '@flybywiresim/fbw-sdk'; + import { MapLayer } from './MapLayer'; import { MapParameters } from '../utils/MapParameters'; import { PaintUtils } from './PaintUtils'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts similarity index 97% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts index d1cae6348b8..46b93928148 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/TrafficLayer.ts @@ -2,13 +2,14 @@ // // SPDX-License-Identifier: GPL-3.0 -import { NdTraffic } from '@shared/NavigationDisplay'; -// import { MathUtils } from '@flybywiresim/fbw-sdk'; -import { TaRaIntrusion } from '@tcas/lib/TcasConstants'; +import { NdTraffic } from '@flybywiresim/fbw-sdk'; import { MapLayer } from './MapLayer'; import { PaintUtils } from './PaintUtils'; import { CanvasMap } from './CanvasMap'; +// TODO move this somewhere better, need to move TCAS stuff into fbw-sdk +declare enum TaRaIntrusion { TRAFFIC = 0, PROXIMITY = 1, TA = 2, RA = 3 } + const DiamondHeight = 18; const DiamondWidth = 12; export class TrafficLayer implements MapLayer { diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts b/fbw-common/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts similarity index 98% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts rename to fbw-common/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts index c0f98aa71d8..2b17daef8c7 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/map/WaypointLayer.ts @@ -2,8 +2,8 @@ // // SPDX-License-Identifier: GPL-3.0 -import { NdSymbol, NdSymbolTypeFlags } from '@shared/NavigationDisplay'; -import { MathUtils } from '@flybywiresim/fbw-sdk'; +import { NdSymbol, NdSymbolTypeFlags, MathUtils } from '@flybywiresim/fbw-sdk'; + import { BitFlags } from '@microsoft/msfs-sdk'; import { MapLayer } from './MapLayer'; import { MapParameters } from '../utils/MapParameters'; diff --git a/fbw-a32nx/src/systems/instruments/src/ND/shared/utils/MapParameters.ts b/fbw-common/src/systems/instruments/src/ND/shared/utils/MapParameters.ts similarity index 96% rename from fbw-a32nx/src/systems/instruments/src/ND/shared/utils/MapParameters.ts rename to fbw-common/src/systems/instruments/src/ND/shared/utils/MapParameters.ts index 494f437bb92..300e34c7fa1 100644 --- a/fbw-a32nx/src/systems/instruments/src/ND/shared/utils/MapParameters.ts +++ b/fbw-common/src/systems/instruments/src/ND/shared/utils/MapParameters.ts @@ -1,4 +1,4 @@ -import { Coordinates } from '@fmgc/flightplanning/data/geo'; +import { Coordinates } from 'msfs-geo'; export class MapParameters { public centerCoordinates: Coordinates; diff --git a/fbw-common/src/systems/instruments/src/ND/style.scss b/fbw-common/src/systems/instruments/src/ND/style.scss new file mode 100644 index 00000000000..fc9a2c06839 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/style.scss @@ -0,0 +1,238 @@ +@import "../MsfsAvionicsCommon/definitions.scss"; +@import "animations"; + +@font-face { + font-family: "Ecam"; + //noinspection CssUnknownTarget + src: url("/Fonts/fbw-a32nx/ECAMFontRegular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "NDChrono"; + //noinspection CssUnknownTarget + src: url("/Fonts/fbw-a32nx/NDChrono.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} + +.nd-svg { + position: absolute; + top: 0; + left: 0; + width: 768px; + height: 768px; + background: transparent; + font-family: "Ecam", monospace !important; +} + +.nd-canvas-map { + transform: rotateX(0deg); +} + +.nd-top-layer { + transform: rotateX(0deg); + background: none; +} + +.TextOutline { + paint-order: stroke fill markers; + + stroke-width: 0.05mm; + stroke: $display-background !important; +} + +$font-factor: 5; + +.FontLargest { + font-size: #{7px * $font-factor}; +} + +.FontLarge { + font-size: #{6.5px * $font-factor}; +} + +.FontMedium { + font-size: #{6px * $font-factor}; +} + +.FontIntermediate { + font-size: #{5.5px * $font-factor}; +} + +.FontSmall { + font-size: #{5px * $font-factor}; +} + +.FontSmallest { + font-size: #{4.5px * $font-factor}; +} + +.FontTiny { + font-size: #{4px * $font-factor}; +} + +.StartAlign { + text-align: start; + text-anchor: start; +} +.MiddleAlign { + text-align: center; + text-anchor: middle; +} +.EndAlign { + text-align: end; + text-anchor: end; +} + +.Magenta { + fill: none; + stroke: $display-magenta; +} +text.Magenta, +tspan.Magenta, +.Magenta text, +.Magenta tspan { + fill: $display-magenta; + stroke: none; +} + +.Cyan { + fill: none; + stroke: $display-cyan; +} +text.Cyan, +tspan.Cyan, +.Cyan text, +.Cyan tspan { + fill: $display-cyan; + stroke: none; +} + +/* .None { + fill: none; + stroke: none; +} */ + +.White { + fill: none; + stroke: $display-white; +} +.White.Fill { + fill: $display-white; + stroke: none; +} +text.White, +tspan.White, +.White text, +.White tspan { + fill: $display-white; + stroke: none; +} + +.Green { + stroke: $display-green; + fill: none; +} + +.Green.Fill { + fill: $display-green; + stroke: none; +} + +text.Green, +tspan.Green, +.Green text, +.Green tspan { + fill: $display-green; + stroke: none; +} + +.Amber { + stroke: $display-amber; + fill: none; +} +text.Amber, +tspan.Amber, +.Amber text, +.Amber tspan { + fill: $display-amber; + stroke: none; +} + +.Yellow { + stroke: $display-yellow; + fill: none; +} +.Yellow.Fill { + fill: $display-yellow; + stroke: none; +} +text.Yellow, +tspan.Yellow, +.Yellow text, +.Yellow tspan { + fill: $display-yellow; + stroke: none; +} + +.Red { + stroke: $display-red; + fill: none; +} +.Red.Fill { + fill: $display-red; + stroke: none; +} +text.Red, +tspan.Red, +.Red text, +.Red tspan { + fill: $display-red; + stroke: none; +} + +.Grey { + stroke: $display-grey; + fill: none; +} +.Grey.Fill { + fill: $display-grey; + stroke: none; +} + + +.BackgroundFill { + fill: $display-background; + fill-rule: evenodd; +} + +text.shadow { + stroke: $display-background; + stroke-width: 1px; + paint-order: stroke; +} + +circle.shadow, +line.shadow, +path.shadow, +rect.shadow { + stroke: $display-background; + fill: none; +} + + +.chrono { + font-family: "NDChrono", monospace !important; +} + +.nd-inverted-map-area { + background: $display-background; + fill: rgb(4,4,5); +} + +path.rounded { + stroke-linecap: round; + stroke-linejoin: round; +} diff --git a/fbw-common/src/systems/instruments/src/ND/tsconfig.json b/fbw-common/src/systems/instruments/src/ND/tsconfig.json new file mode 100644 index 00000000000..2d56720368e --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/tsconfig.json @@ -0,0 +1,33 @@ +{ + "extends": "../../../tsconfig.json", + + "compilerOptions": { + "incremental": false /* Enables incremental builds */, + "target": "es2017" /* Specifies the ES2017 target, compatible with Coherent GT */, + "module": "es2015" /* Ensures that modules are at least es2015 */, + "strict": false /* Enables strict type checking, highly recommended but optional */, + "esModuleInterop": true /* Emits additional JS to work with CommonJS modules */, + "skipLibCheck": true /* Skip type checking on library .d.ts files */, + "forceConsistentCasingInFileNames": true /* Ensures correct import casing */, + "moduleResolution": "node" /* Enables compatibility with MSFS SDK bare global imports */, + "jsxFactory": "FSComponent.buildComponent" /* Required for FSComponent framework JSX */, + "jsxFragmentFactory": "FSComponent.Fragment" /* Required for FSComponent framework JSX */, + "jsx": "react", /* Required for FSComponent framework JSX */ + "paths": { + "@datalink/aoc": ["../../../fbw-common/src/systems/datalink/aoc/src/index.ts"], + "@datalink/atc": ["../../../fbw-common/src/systems/datalink/atc/src/index.ts"], + "@datalink/common": ["../../../fbw-common/src/systems/datalink/common/src/index.ts"], + "@datalink/router": ["../../../fbw-common/src/systems/datalink/router/src/index.ts"], + "@failures": ["./failures/src/index.ts"], + "@fmgc/*": ["./fmgc/src/*"], + "@instruments/common/*": ["./instruments/src/Common/*"], + "@localization/*": ["../localization/*"], + "@sentry/*": ["./sentry-client/src/*"], + "@simbridge/*": ["./simbridge-client/src/*"], + "@shared/*": ["./shared/src/*"], + "@tcas/*": ["./tcas/src/*"], + "@typings/*": ["../../../fbw-common/src/typings/*"], + "@flybywiresim/fbw-sdk": ["../../../fbw-common/src/systems/index-no-react.ts"] + } + } +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericAdirsEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericAdirsEvents.ts new file mode 100644 index 00000000000..fcd17b21e5b --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericAdirsEvents.ts @@ -0,0 +1,23 @@ +export interface GenericAdirsEvents { + pitch: number; + roll: number; + magHeadingRaw: number; + baroCorrectedAltitude: number; + speed: number; + vsInert: number; + vsBaro: number; + magTrackRaw: number; + groundSpeed: number; + trueAirSpeed: number; + windDirection: number; + windSpeed: number; + fpaRaw: number; + daRaw: number; + mach: number; + latitude: number; + longitude: number; + latAccRaw: number; + irMaintWordRaw: number; + trueHeadingRaw: number; + trueTrackRaw: number; +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericDisplayManagementEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericDisplayManagementEvents.ts new file mode 100644 index 00000000000..2df2113f8b6 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericDisplayManagementEvents.ts @@ -0,0 +1,8 @@ +import { Arinc429WordData } from '../../../../shared/src/arinc429'; + +export interface GenericDisplayManagementEvents { + trueRefActive: boolean, + trueRefPushButton: boolean, + heading: Arinc429WordData, + track: Arinc429WordData, +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericFcuEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericFcuEvents.ts new file mode 100644 index 00000000000..b2eda1c6837 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericFcuEvents.ts @@ -0,0 +1,11 @@ +import { EfisNdMode, EfisOption, NavAidMode } from '../../NavigationDisplay'; + +export interface GenericFcuEvents { + ndRangeSetting: number, + ndMode: EfisNdMode, + option: EfisOption, + navaidMode1: NavAidMode, + navaidMode2: NavAidMode, + /** State of the LS pushbutton on the EFIS control panel. */ + efisLsActive: boolean, +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericFlightGuidanceEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericFlightGuidanceEvents.ts new file mode 100644 index 00000000000..d4fe3035c78 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericFlightGuidanceEvents.ts @@ -0,0 +1,38 @@ +export enum LateralMode { + NONE = 0, + HDG = 10, + TRACK = 11, + NAV = 20, + LOC_CPT = 30, + LOC_TRACK = 31, + LAND = 32, + FLARE = 33, + ROLL_OUT = 34, + RWY = 40, + RWY_TRACK = 41, + GA_TRACK = 50, +} + +export enum ArmedLateralMode { + NAV = 0, + LOC = 1, +} + +export enum ArmedVerticalMode { + ALT = 0, + ALT_CST = 1, + CLB = 2, + DES = 3, + GS = 4, + FINAL = 5, + TCAS = 6, +} + +export interface GenericFlightGuidanceEvents { + 'fg.fma.lateralMode': LateralMode, + 'fg.fma.lateralArmedBitmask': number, +} + +export function isArmed(bitmask: number, armedBit: ArmedVerticalMode | ArmedLateralMode): boolean { + return ((bitmask >> armedBit) & 1) === 1; +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericFlightManagementBusEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericFlightManagementBusEvents.ts new file mode 100644 index 00000000000..256a90d6eb8 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericFlightManagementBusEvents.ts @@ -0,0 +1,9 @@ +export interface GenericFlightManagementBusEvents { + 'fm.1.healthy_discrete': boolean, + + 'fm.2.healthy_discrete': boolean, + + 'fm.1.tuning_discrete_word': number, + + 'fm.2.tuning_discrete_word': number, +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericFmsEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericFmsEvents.ts new file mode 100644 index 00000000000..c173d4f42dc --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericFmsEvents.ts @@ -0,0 +1,19 @@ +export interface GenericFmsEvents { + ndMessageFlags: number, + crossTrackError: number, + linearDeviationActive: boolean; + targetAltitude: number; + verticalProfileLatched: boolean; + showSpeedMargins: boolean; + upperSpeedMargin: number; + lowerSpeedMargin: number; + rnp: number; + toWptIdent0: number; + toWptIdent1: number; + toWptBearing: number; + toWptTrueBearing: number; + toWptDistance: number; + toWptEta: number; + apprMessage0: number; + apprMessage1: number; +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericSwitchingPanelEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericSwitchingPanelEvents.ts new file mode 100644 index 00000000000..1714a94e960 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericSwitchingPanelEvents.ts @@ -0,0 +1,5 @@ +export interface GenericSwitchingPanelEvents { + attHdgKnob: number; + airKnob: number; + dmcKnob: number; +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericTawsEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericTawsEvents.ts new file mode 100644 index 00000000000..af473418962 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericTawsEvents.ts @@ -0,0 +1,12 @@ +export enum TerrainLevelMode { + PeaksMode = 0, + Warning = 1, + Caution = 2, +} + +export interface GenericTawsEvents { + 'egpwc.minElevation': number, + 'egpwc.minElevationMode': TerrainLevelMode, + 'egpwc.maxElevation': number, + 'egpwc.maxElevationMode': TerrainLevelMode, +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericTcasEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericTcasEvents.ts new file mode 100644 index 00000000000..431f8287767 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericTcasEvents.ts @@ -0,0 +1,5 @@ +export interface GenericTcasEvents { + tcasTaOnly: boolean, + tcasFault: boolean, + tcasMode: number, +} diff --git a/fbw-common/src/systems/instruments/src/ND/types/GenericVorEvents.ts b/fbw-common/src/systems/instruments/src/ND/types/GenericVorEvents.ts new file mode 100644 index 00000000000..bdaad71b9c9 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/ND/types/GenericVorEvents.ts @@ -0,0 +1,63 @@ +export interface GenericVorEvents { + nav1Ident: string, + nav1Frequency: number, + nav1HasDme: boolean, + nav1DmeDistance: NauticalMiles, + nav1RelativeBearing: Degrees, + nav1Obs: Degrees, + nav1Localizer: Degrees, + nav1RadialError: Degrees, + nav1Available: boolean, + nav1StationDeclination: Degrees, + nav1Location: LatLongAlt, + + nav2Ident: string, + nav2Frequency: number, + nav2HasDme: boolean, + nav2DmeDistance: NauticalMiles, + nav2RelativeBearing: Degrees, + nav2Obs: Degrees, + nav2Localizer: Degrees, + nav2RadialError: Degrees, + nav2Available: boolean, + nav2StationDeclination: Degrees, + nav2Location: LatLongAlt, + + nav3Ident: string, + nav3Frequency: number, + nav3HasDme: boolean, + nav3DmeDistance: NauticalMiles, + nav3RelativeBearing: Degrees, + nav3Obs: Degrees, + nav3Localizer: Degrees, + nav3RadialError: Degrees, + nav3Available: boolean, + nav3StationDeclination: Degrees, + nav3Location: LatLongAlt, + + nav4Ident: string, + nav4Frequency: number, + nav4HasDme: boolean, + nav4DmeDistance: NauticalMiles, + nav4RelativeBearing: Degrees, + nav4Obs: Degrees, + nav4Localizer: Degrees, + nav4RadialError: Degrees, + nav4Available: boolean, + nav4StationDeclination: Degrees, + nav4Location: LatLongAlt, + + localizerValid: boolean, + glideSlopeValid: boolean, + glideSlopeDeviation: number, + + adf1Ident: string, + adf1ActiveFrequency: number, + adf1SignalStrength: number, + adf1Radial: number + + adf2Ident: string, + adf2ActiveFrequency: number, + adf2SignalStrength: number, + adf2Radial: number, +} diff --git a/fbw-a32nx/src/systems/shared/src/NavigationDisplay.ts b/fbw-common/src/systems/instruments/src/NavigationDisplay.ts similarity index 92% rename from fbw-a32nx/src/systems/shared/src/NavigationDisplay.ts rename to fbw-common/src/systems/instruments/src/NavigationDisplay.ts index a5413cc6d1a..3915da48a3e 100644 --- a/fbw-a32nx/src/systems/shared/src/NavigationDisplay.ts +++ b/fbw-common/src/systems/instruments/src/NavigationDisplay.ts @@ -6,7 +6,12 @@ import { Coordinates } from '@fmgc/flightplanning/data/geo'; export type EfisSide = 'L' | 'R' export type EfisNdRangeValue = 10 | 20 | 40 | 80 | 160 | 320; -export const rangeSettings: EfisNdRangeValue[] = [10, 20, 40, 80, 160, 320]; + +export const efisRangeSettings: EfisNdRangeValue[] = [10, 20, 40, 80, 160, 320]; + +export type EfisOansNdRangeValue = -1 | 10 | 20 | 40 | 80 | 160 | 320; + +export const efisOansRangeSettings: EfisOansNdRangeValue[] = [-1, 10, 20, 40, 80, 160, 320]; export enum EfisNdMode { ROSE_ILS, diff --git a/fbw-common/src/systems/instruments/src/index.ts b/fbw-common/src/systems/instruments/src/index.ts index f9bcfc873d4..772b7cbf3df 100644 --- a/fbw-common/src/systems/instruments/src/index.ts +++ b/fbw-common/src/systems/instruments/src/index.ts @@ -1,5 +1,6 @@ export * from './defaults'; export * from './metarTypes'; +export * from './NavigationDisplay'; export * from './NXLogic'; export * from './NXUnits'; export * from './RateMultiplierKnob'; diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/Arinc429ConsumerSubject.ts b/fbw-common/src/systems/shared/src/Arinc429ConsumerSubject.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/Arinc429ConsumerSubject.ts rename to fbw-common/src/systems/shared/src/Arinc429ConsumerSubject.ts diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject.ts b/fbw-common/src/systems/shared/src/Arinc429RegisterSubject.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/Arinc429RegisterSubject.ts rename to fbw-common/src/systems/shared/src/Arinc429RegisterSubject.ts diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/ArincConsumer.ts b/fbw-common/src/systems/shared/src/ArincConsumer.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/ArincConsumer.ts rename to fbw-common/src/systems/shared/src/ArincConsumer.ts diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/ArincEventBus.ts b/fbw-common/src/systems/shared/src/ArincEventBus.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/ArincEventBus.ts rename to fbw-common/src/systems/shared/src/ArincEventBus.ts diff --git a/fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/ArincEventBusSubscriber.ts b/fbw-common/src/systems/shared/src/ArincEventBusSubscriber.ts similarity index 100% rename from fbw-a32nx/src/systems/instruments/src/MsfsAvionicsCommon/ArincEventBusSubscriber.ts rename to fbw-common/src/systems/shared/src/ArincEventBusSubscriber.ts diff --git a/fbw-a32nx/src/systems/shared/src/FmMessages.ts b/fbw-common/src/systems/shared/src/FmMessages.ts similarity index 100% rename from fbw-a32nx/src/systems/shared/src/FmMessages.ts rename to fbw-common/src/systems/shared/src/FmMessages.ts diff --git a/fbw-common/src/systems/shared/src/MathUtils.ts b/fbw-common/src/systems/shared/src/MathUtils.ts index 997396cc103..8b3e0a37593 100644 --- a/fbw-common/src/systems/shared/src/MathUtils.ts +++ b/fbw-common/src/systems/shared/src/MathUtils.ts @@ -76,6 +76,22 @@ export class MathUtils { return diff; } + /** + * Gets the smallest angle between two angles + * @param angle1 First angle in degrees + * @param angle2 Second angle in degrees + * @returns {number} Smallest angle between angle1 and angle2 in degrees + */ + public static getSmallestAngle(angle1: number, angle2: number): number { + let smallestAngle = angle1 - angle2; + if (smallestAngle > 180) { + smallestAngle -= 360; + } else if (smallestAngle < -180) { + smallestAngle += 360; + } + return smallestAngle; + } + public static adjustAngleForTurnDirection(angle: Degrees, turnDirection: TurnDirection) { let ret = angle; diff --git a/fbw-common/src/systems/shared/src/PathVector.ts b/fbw-common/src/systems/shared/src/PathVector.ts new file mode 100644 index 00000000000..97f593105f6 --- /dev/null +++ b/fbw-common/src/systems/shared/src/PathVector.ts @@ -0,0 +1,78 @@ +import { Coordinates } from '@fmgc/flightplanning/data/geo'; +import { arcLength, pointOnArc, pointOnCourseToFix } from '@fmgc/guidance/lnav/CommonGeometry'; + +export enum PathVectorType { + Line, + Arc, + DebugPoint, +} + +export enum DebugPointColour { + White, + Green, + Yellow, + Cyan, + Magenta, +} + +export interface ArcPathVector { + type: PathVectorType.Arc, + startPoint: Coordinates, + endPoint: Coordinates, + centrePoint: Coordinates, + sweepAngle: Degrees, +} + +export interface LinePathVector { + type: PathVectorType.Line, + startPoint: Coordinates, + endPoint: Coordinates, +} + +export interface DebugPointPathVector { + type: PathVectorType.DebugPoint, + startPoint: Coordinates, + annotation?: string, + colour?: DebugPointColour, +} + +export type PathVector = LinePathVector | ArcPathVector | DebugPointPathVector + +export function pathVectorLength(vector: PathVector) { + if (vector.type === PathVectorType.Line) { + return Avionics.Utils.computeGreatCircleDistance(vector.startPoint, vector.endPoint); + } + + if (vector.type === PathVectorType.Arc) { + const radius = Avionics.Utils.computeGreatCircleDistance(vector.startPoint, vector.centrePoint); + + return arcLength(radius, vector.sweepAngle); + } + + return 0; +} + +export function pathVectorValid(vector: PathVector) { + switch (vector.type) { + case PathVectorType.Line: + return !!(vector.startPoint?.lat && vector.endPoint?.lat); + case PathVectorType.Arc: + return !!(vector.endPoint?.lat && vector.centrePoint?.lat && vector.sweepAngle); + case PathVectorType.DebugPoint: + return !!vector.startPoint?.lat; + default: + return true; + } +} + +export function pathVectorPoint(vector: PathVector, distanceFromEnd: NauticalMiles): Coordinates | undefined { + if (vector.type === PathVectorType.Line) { + return pointOnCourseToFix(distanceFromEnd, Avionics.Utils.computeGreatCircleHeading(vector.startPoint, vector.endPoint), vector.endPoint); + } + + if (vector.type === PathVectorType.Arc) { + return pointOnArc(distanceFromEnd, vector.endPoint, vector.centrePoint, vector.sweepAngle); + } + + return undefined; +} diff --git a/fbw-common/src/systems/shared/src/index.ts b/fbw-common/src/systems/shared/src/index.ts index 05fce840983..86e847c07e0 100644 --- a/fbw-common/src/systems/shared/src/index.ts +++ b/fbw-common/src/systems/shared/src/index.ts @@ -1,17 +1,24 @@ export * from './navigraph'; export * from './ApproachUtils'; export * from './arinc429'; +export * from './Arinc429ConsumerSubject'; +export * from './Arinc429RegisterSubject'; +export * from './ArincConsumer'; +export * from './ArincEventBus'; +export * from './ArincEventBusSubscriber'; export * from './ata'; export * from './array'; export * from './bitFlags'; export * from './config'; export * from './Constants'; export * from './GenericDataListenerSync'; +export * from './FmMessages'; export * from './logic'; export * from './MathUtils'; export * from './navdata'; export * from './notification'; export * from './parseMetar'; +export * from './PathVector'; export * from './persistence'; export * from './popup'; export * from './RunwayUtils';