diff --git a/fbw-a380x/mach.config.js b/fbw-a380x/mach.config.js index 0f53acc371e6..1a751a10370b 100644 --- a/fbw-a380x/mach.config.js +++ b/fbw-a380x/mach.config.js @@ -28,6 +28,7 @@ module.exports = { typecheckingPlugin(), ], instruments: [ + msfsAvionicsInstrument('AtcMailbox'), msfsAvionicsInstrument('Clock'), msfsAvionicsInstrument('EWD'), msfsAvionicsInstrument('FCU', 'FcuBaseInstrument.ts'), diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg index bf497acb6f7a..60212725b7bc 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg @@ -46,6 +46,7 @@ pixel_size=768,1024 texture=$SCREEN_DU_SD htmlgauge00=A380X/SD/sd.html?duID=7, 0,0,768,1024 +htmlgauge01=A380X/AtcMailbox/atcmailbox.html?duID=7, 0,0,768,1024 [VCockpit05] size_mm=768,1024 diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/sound/sound.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/sound/sound.xml index 15a182419902..97a7214fa9ce 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/sound/sound.xml +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/sound/sound.xml @@ -1177,7 +1177,7 @@ - + diff --git a/fbw-a380x/src/systems/instruments/src/AtcMailbox/.eslintrc.js b/fbw-a380x/src/systems/instruments/src/AtcMailbox/.eslintrc.js new file mode 100644 index 000000000000..5001200a0c21 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/.eslintrc.js @@ -0,0 +1,15 @@ +'use strict'; + +module.exports = { + extends: ['../../../../../../.eslintrc.js', 'plugin:jsdoc/recommended-typescript-error'], + + plugins: ['eslint-plugin-jsdoc'], + + // 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/AtcMailbox/AtcMailbox.tsx b/fbw-a380x/src/systems/instruments/src/AtcMailbox/AtcMailbox.tsx new file mode 100644 index 000000000000..01f0a8b12e28 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/AtcMailbox.tsx @@ -0,0 +1,61 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { DisplayComponent, EventBus, FSComponent, Subject, VNode } from '@microsoft/msfs-sdk'; +import { Button } from 'instruments/src/MFD/pages/common/Button'; +import { MouseCursor } from 'instruments/src/MFD/pages/common/MouseCursor'; +import { CdsDisplayUnit, DisplayUnitID } from '../MsfsAvionicsCommon/CdsDisplayUnit'; + +import './style.scss'; + +export interface AtcMailboxProps { + readonly bus: EventBus; +} + +export class AtcMailbox extends DisplayComponent { + private readonly topRef = FSComponent.createRef(); + + private readonly mouseCursorRef = FSComponent.createRef(); + + private onMouseMove(ev: MouseEvent) { + this.mouseCursorRef.getOrDefault()?.updatePosition(ev.clientX, ev.clientY - 768); + } + + private onMouseMoveHandler = this.onMouseMove.bind(this); + + public onAfterRender(node: VNode): void { + super.onAfterRender(node); + + this.topRef.instance.addEventListener('mousemove', this.onMouseMoveHandler); + } + + destroy(): void { + this.topRef.getOrDefault()?.removeEventListener('mousemove', this.onMouseMoveHandler); + + super.destroy(); + } + + render(): VNode | null { + return ( + +
+
+ +
+
+
+
+
+
+
+
+
+ + +
+ +
+ + ); + } +} diff --git a/fbw-a380x/src/systems/instruments/src/AtcMailbox/config.json b/fbw-a380x/src/systems/instruments/src/AtcMailbox/config.json new file mode 100644 index 000000000000..16331a90ebbf --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/config.json @@ -0,0 +1,5 @@ +{ + "index": "./instrument.tsx", + "name": "AtcMailbox", + "isInteractive": true +} diff --git a/fbw-a380x/src/systems/instruments/src/AtcMailbox/instrument.tsx b/fbw-a380x/src/systems/instruments/src/AtcMailbox/instrument.tsx new file mode 100644 index 000000000000..21404330143b --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/instrument.tsx @@ -0,0 +1,105 @@ +import { + FSComponent, + EventBus, + HEventPublisher, + InstrumentBackplane, + FsInstrument, + FsBaseInstrument, + ClockPublisher, +} from '@microsoft/msfs-sdk'; +import { FailuresConsumer } from '@flybywiresim/fbw-sdk'; +import { AtcMailbox } from 'instruments/src/AtcMailbox/AtcMailbox'; + +class AtcMailboxInstrument implements FsInstrument { + private readonly bus = new EventBus(); + + private readonly backplane = new InstrumentBackplane(); + + private readonly clockPublisher = new ClockPublisher(this.bus); + + private readonly hEventPublisher = new HEventPublisher(this.bus); + + private readonly failuresConsumer = new FailuresConsumer('A32NX'); + + constructor(public readonly instrument: BaseInstrument) { + this.hEventPublisher = new HEventPublisher(this.bus); + + this.backplane.addPublisher('hEvent', this.hEventPublisher); + this.backplane.addPublisher('clock', this.clockPublisher); + + this.doInit(); + } + + public doInit(): void { + this.backplane.init(); + + const atcMailbox = document.getElementById('AtcMailbox_CONTENT'); + + FSComponent.render(, document.getElementById('AtcMailbox_CONTENT')); + + // Remove "instrument didn't load" text + atcMailbox?.querySelector(':scope > h1')?.remove(); + } + + /** + * A callback called when the instrument gets a frame update. + */ + public Update(): void { + this.backplane.onUpdate(); + this.failuresConsumer.update(); + } + + public onInteractionEvent(args: string[]): void { + this.hEventPublisher.dispatchHEvent(args[0]); + } + + public onGameStateChanged(_oldState: GameState, _newState: GameState): void { + // noop + } + + public onFlightStart(): void { + // noop + } + + public onSoundEnd(_soundEventId: Name_Z): void { + // noop + } + + public onPowerOn(): void { + // noop + } + + public onPowerOff(): void { + // noop + } +} + +class A380X_AtcMailbox extends FsBaseInstrument { + public constructInstrument(): AtcMailboxInstrument { + return new AtcMailboxInstrument(this); + } + + public get isInteractive(): boolean { + return true; + } + + public get templateID(): string { + return 'A380X_AtcMailbox'; + } + + /** @inheritdoc */ + public onPowerOn(): void { + super.onPowerOn(); + + this.fsInstrument.onPowerOn(); + } + + /** @inheritdoc */ + public onShutDown(): void { + super.onShutDown(); + + this.fsInstrument.onPowerOff(); + } +} + +registerInstrument('a380x-atc-mailbox', A380X_AtcMailbox); diff --git a/fbw-a380x/src/systems/instruments/src/AtcMailbox/style.scss b/fbw-a380x/src/systems/instruments/src/AtcMailbox/style.scss new file mode 100644 index 000000000000..d2d156b4c687 --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/style.scss @@ -0,0 +1,54 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +@import "../MsfsAvionicsCommon/definitions.scss"; + +.atc-mailbox-top-layout { + display: grid; + grid-template-columns: 13% auto 18%; + height: 256px; + width: 768px; + position: absolute; + top: 768px; +} + +.atc-mailbox-left-layout { + display: flex; + flex-direction: column; + justify-content: flex-end; + border-right: 2px solid $display-white; +} + +.atc-mailbox-center-layout { + display: flex; + flex-direction: column; + justify-content: flex-end; +} + +.atc-mailbox-right-layout { + display: flex; + flex-direction: column; + justify-content: space-between; + border-left: 2px solid $display-white; +} + +.atc-mailbox-center-bottom { + display: flex; + flex: 1; + flex-direction: row; +} + +.atc-mailbox-center-top { + display: flex; + flex: 8; + border-bottom: 2px solid white; +} + +.atc-mailbox-cb-1 { + flex: 1; + border-right: 2px solid white; +} + +.atc-mailbox-cb-2 { + flex: 1; +} diff --git a/fbw-a380x/src/systems/instruments/src/AtcMailbox/tsconfig.json b/fbw-a380x/src/systems/instruments/src/AtcMailbox/tsconfig.json new file mode 100644 index 000000000000..b051de3a024f --- /dev/null +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/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": true /* 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-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx b/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx index 015199ccdfde..93f210bbed8a 100644 --- a/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx +++ b/fbw-a380x/src/systems/instruments/src/Common/LegacyCdsDisplayUnit.tsx @@ -45,6 +45,7 @@ const DisplayUnitToPotentiometer: { [k in DisplayUnitID]: number } = { interface DisplayUnitProps { displayUnitId: DisplayUnitID; failed?: boolean; + hideBootTestScreens?: boolean; } enum DisplayUnitState { @@ -63,7 +64,7 @@ function BacklightBleed(props) { } export const LegacyCdsDisplayUnit = forwardRef>( - ({ displayUnitId, failed, children }, ref) => { + ({ displayUnitId, failed, hideBootTestScreens, 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); @@ -167,7 +168,7 @@ export const LegacyCdsDisplayUnit = forwardRef @@ -181,7 +182,7 @@ export const LegacyCdsDisplayUnit = forwardRef diff --git a/fbw-a380x/src/systems/instruments/src/SD/Mailbox.tsx b/fbw-a380x/src/systems/instruments/src/SD/Mailbox.tsx deleted file mode 100644 index 3d8dc6b52cdf..000000000000 --- a/fbw-a380x/src/systems/instruments/src/SD/Mailbox.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useRef } from 'react'; - -import { Layer } from '@instruments/common/utils'; - -export const Mailbox = () => { - const ref = useRef(null); - - return ( - <> - - - {/* Lower status */} - - - - - - {/* Message area */} - - {/*ATC DATALINK COM - NOT AVAIL*/} - - {/* Buttons */} - - - - RECALL - - - - - - CLOSE - - - - - - PRINT - - - {/*{mouse.isOver && }*/} - - - ); -}; diff --git a/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx b/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx index fad025d9080d..3c3c5e535921 100644 --- a/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx +++ b/fbw-a380x/src/systems/instruments/src/SD/SystemDisplay.tsx @@ -26,7 +26,6 @@ import { CruisePage } from './Pages/Cruise/CruisePage'; import { StatusPage } from './Pages/Status/StatusPage'; import { StatusArea } from './StatusArea'; -import { Mailbox } from './Mailbox'; import '../index.scss'; import { useArinc429Var, useUpdate } from '@flybywiresim/fbw-sdk'; @@ -296,11 +295,10 @@ export const SystemDisplay = () => { }; return ( - + {PAGES[currentPage]} - );