diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 index b373430eeba..7c654630635 100644 --- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 @@ -197,25 +197,12 @@ }, { "seats": [ - { - "type": 1 - }, - { - "type": 1 - }, - { - "type": 1 - }, - { - "type": 1, - "yOffset": 19 - }, - { - "type": 1 - }, - { - "type": 1 - } + { "type": 1}, + { "type": 1}, + { "type": 1}, + { "type": 1, "yOffset": 19}, + { "type": 1}, + { "type": 1} ], "x": 0, "y": 0, @@ -224,25 +211,12 @@ }, { "seats": [ - { - "type": 1 - }, - { - "type": 1 - }, - { - "type": 1 - }, - { - "type": 1, - "yOffset": 19 - }, - { - "type": 1 - }, - { - "type": 1 - } + { "type": 1}, + { "type": 1}, + { "type": 1}, + { "type": 1, "yOffset": 19}, + { "type": 1}, + { "type": 1} ], "x": 0, "y": 0, diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 index ab20d38835e..ff09c0054a3 100644 --- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 @@ -17,7 +17,12 @@ { "configMajorVersion": 0, "configMinorVersion": 1, - "_type": 1, + "_canvas": { + "width": 1000, + "height": 150, + "canvasX": 243, + "canvasY": 78 + }, "chartLimits": { "weight": { "min": 35000, @@ -66,5 +71,88 @@ "y": 0.29 } } - } + }, + "_seatDisplay": [ + { + // NarrowbodyEconomy + len: 25.4, + wid: 19.2, + padX: 6.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // NarrowbodyEconomyEmergency + len: 25.4, + wid: 19.2, + padX: 13.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // WidebodyEconomy + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyEconomyEmergency + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyBusinessFlatRight + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodyBusinessFlatLeft + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodySuiteRight + len: 35, + wid: 20, + padX: 2, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodySuiteLeft + len: 35, + wid: 20, + padX: 5, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodyPremiumEconomy + len: 18, + wid: 13.64, + padX: 2, + padY: 0, + imageX: 18, + imageY: 13.64, + } + ] } diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 index 844671c5f57..afff12577ae 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 @@ -17,7 +17,12 @@ { "configMajorVersion": 0, "configMinorVersion": 1, - "_type": 2, + "_canvas": { + "width": 1000, + "height": 150, + "canvasX": 146, + "canvasY": 71 + }, "chartLimits": { "weight": { "min": 235000, @@ -41,5 +46,88 @@ "mlw": { "x1": 0.75, "x2": 0.12, "y": 0.47 }, "mzfw": { "x1": 0.75, "x2": 0.12, "y": 0.57 } } - } + }, + "_seatDisplay": [ + { + // NarrowbodyEconomy + len: 25.4, + wid: 19.2, + padX: 6.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // NarrowbodyEconomyEmergency + len: 25.4, + wid: 19.2, + padX: 13.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // WidebodyEconomy + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyEconomyEmergency + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyBusinessFlatRight + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodyBusinessFlatLeft + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodySuiteRight + len: 35, + wid: 20, + padX: 2, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodySuiteLeft + len: 35, + wid: 20, + padX: 5, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodyPremiumEconomy + len: 18, + wid: 13.64, + padX: 2, + padY: 0, + imageX: 18, + imageY: 13.64, + } + ] } diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/Chart/ChartWidget.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/Chart/ChartWidget.tsx index 36c6151d65a..55ae2dd4135 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/Chart/ChartWidget.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/Chart/ChartWidget.tsx @@ -1,15 +1,15 @@ // Copyright (c) 2023-2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { usePersistentProperty, useSimVar, Units } from '@flybywiresim/fbw-sdk'; +import { usePersistentProperty, useSimVar, Units, PayloadChartLimits, AirframePerformanceEnvelope } from '@flybywiresim/fbw-sdk'; import React, { useEffect, useRef, useState } from 'react'; -import { CanvasConst, PerformanceEnvelope, ChartLimits } from './Constants'; +import { CanvasConst } from './Constants'; interface ChartWidgetProps { width: number, height: number, - envelope: PerformanceEnvelope, - limits: ChartLimits, + envelope: AirframePerformanceEnvelope, + limits: PayloadChartLimits, gw: number, cg: number, mldw: number, @@ -276,9 +276,9 @@ export const ChartWidget: React.FC = ({ {cgAxis} {weightAxis}

{usingMetric ? 'x 1000 kgs' : 'x 1000 lbs'}

-

{flightPhase <= 1 || flightPhase >= 7 ? 'MTOW' : 'FLIGHT'}

+

{flightPhase <= 1 || flightPhase >= 7 ? 'MTOW' : 'FLIGHT'}

MLDW

-

MZFW

+

MZFW

); }; diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx index 24393f9a486..d43d482a5b6 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx @@ -4,13 +4,12 @@ /* eslint-disable max-len */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { CloudArrowDown } from 'react-bootstrap-icons'; -import { SeatFlags, Units, usePersistentNumberProperty, usePersistentProperty, useSeatFlags, useSimVar } from '@flybywiresim/fbw-sdk'; +import { CargoStationInfo, PaxStationInfo, SeatFlags, Units, usePersistentNumberProperty, usePersistentProperty, useSeatFlags, useSimVar } from '@flybywiresim/fbw-sdk'; import { setPayloadImported, useAppDispatch, Card, t, TooltipWrapper, SelectGroup, SelectItem, PromptModal, useModals } from '@flybywiresim/flypad'; import { SeatOutlineBg } from '../../../../Assets/SeatOutlineBg'; import { BoardingInput, MiscParamsInput, PayloadInputTable } from '../PayloadElements'; import { CargoWidget } from './CargoWidget'; import { ChartWidget } from '../Chart/ChartWidget'; -import { CargoStationInfo, PaxStationInfo } from '../Seating/Constants'; import { SeatMapWidget } from '../Seating/SeatMapWidget'; import { PayloadProps } from '../PayloadPage'; @@ -188,7 +187,7 @@ export const A320Payload: React.FC = ({ fillStation(i, parseFloat(Number((Math.ceil((seatMap[i].capacity / maxPax) * 1e2) / 1e2).toExponential(2)).toPrecision(3)), numOfPax); } fillStation(0, 1, paxRemaining); - }, [maxPax, ...seatMap, totalPaxDesired]); + }, [maxPax, seatMap, totalPaxDesired]); const setTargetCargo = useCallback((numberOfPax: number, freight: number, perBagWeight: number = paxBagWeight) => { const bagWeight = numberOfPax * perBagWeight; @@ -206,7 +205,7 @@ export const A320Payload: React.FC = ({ fillCargo(i, cargoMap[i].weight / maxCargo, loadableCargoWeight); } fillCargo(0, 1, remainingWeight); - }, [maxCargo, ...cargoMap, ...cargoDesired, paxBagWeight]); + }, [maxCargo, cargoMap, ...cargoDesired, paxBagWeight]); const processZfw = useCallback((newZfw) => { let paxCargoWeight = newZfw - emptyWeight; @@ -455,14 +454,25 @@ export const A320Payload: React.FC = ({ return [base, primary, secondary]; }, [theme]); - if (airframeInfo === null) return (<>); return (
- +
@@ -592,7 +602,7 @@ export const A320Payload: React.FC = ({ width={525} height={511} envelope={airframeInfo.designLimits.performanceEnvelope} - limits={flypadInfo.chartLimits} + limits={flypadInfo.payloadChartLimits} cg={boardingStarted ? Math.round(gwCgMac * 100) / 100 : Math.round(desiredGwCgMac * 100) / 100} gw={boardingStarted ? Math.round(gw) : Math.round(gwDesired)} mldwCg={boardingStarted ? Math.round(gwCgMac * 100) / 100 : Math.round(desiredGwCgMac * 100) / 100} diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx index a9bc8e3d831..bdd865870f7 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx @@ -6,12 +6,6 @@ import React from 'react'; import { ArrowLeftRight, BoxArrowRight, BriefcaseFill, CaretDownFill, PersonFill, Shuffle, StopCircleFill } from 'react-bootstrap-icons'; import { AirframeInfo, Units } from '@flybywiresim/fbw-sdk'; import { ProgressBar, t, TooltipWrapper, SimpleInput } from '@flybywiresim/flypad'; -import { CargoStationInfo, PaxStationInfo } from './Seating/Constants'; - -export type Loadsheet = { - specs: AirframeSpec, - seatMap: PaxStationInfo[] -} export type AirframeSpec = { prefix: string, @@ -61,6 +55,16 @@ export const PayloadValueInput: React.FC = ({ min, max,
); +// TODO: To be removed, relocated from Constants +interface CargoStationInfo { + name: string, + weight: number, + simVar: string, + stationIndex: number, + progressBarWidth: number, + position: number, +} + interface CargoBarProps { cargoId: number, cargo: number[], @@ -284,176 +288,173 @@ export const PayloadInputTable: React.FC = ( processZfw, processGw, setDisplayZfw, }, -) => { - if (airframeInfo == null) return (<>); - return ( - - - - - - - - - - - - - - - - +) => ( +
- {' '} - - {t('Ground.Payload.Planned')} - - {t('Ground.Payload.Current')} -
- {t('Ground.Payload.Passengers')} - - -
- 0 ? maxPax : 999} - value={totalPaxDesired} - onBlur={(x) => { - if (!Number.isNaN(parseInt(x) || parseInt(x) === 0)) { - setTargetPax(parseInt(x)); - setTargetCargo(parseInt(x), 0); - } - }} - unit="PAX" - disabled={BoardingInProgress} - /> -
-
-
- -
+ + + + + + + - - - - - + + + + + + + - - - - - - - + + - + + + + + + + + + + + - - - -
+ {' '} + + {t('Ground.Payload.Planned')} + + {t('Ground.Payload.Current')} +
- {t('Ground.Payload.Cargo')} - - -
- 0 ? Math.round(Units.kilogramToUser(maxCargo)) : 99999} - value={Units.kilogramToUser(totalCargoDesired)} - onBlur={(x) => { - if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) { - setTargetCargo(0, Units.userToKilogram(parseInt(x))); - } - }} - unit={massUnitForDisplay} - disabled={BoardingInProgress} - /> -
-
-
- -
+ {t('Ground.Payload.Passengers')} + + +
+ 0 ? maxPax : 999} + value={totalPaxDesired} + onBlur={(x) => { + if (!Number.isNaN(parseInt(x) || parseInt(x) === 0)) { + setTargetPax(parseInt(x)); + setTargetCargo(parseInt(x), 0); + } + }} + unit="PAX" + disabled={BoardingInProgress} + /> +
+
+
+ +
- {displayZfw ? t('Ground.Payload.ZFW') : t('Ground.Payload.GW')} - - {(displayZfw - ? ( - -
- { - if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) processZfw(Units.userToKilogram(parseInt(x))); - }} - unit={massUnitForDisplay} - disabled={BoardingInProgress} - /> -
-
- ) - : ( - -
- { - if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) processGw(Units.userToKilogram(parseInt(x))); - }} - unit={massUnitForDisplay} - disabled={BoardingInProgress} - /> -
-
- ) - )} -
- -
-
-
- {t(displayZfw ? 'Ground.Payload.ZFWCG' : 'Ground.Payload.GWCG')} -
-
- -
+
+ {t('Ground.Payload.Cargo')} + + +
+ 0 ? Math.round(Units.kilogramToUser(maxCargo)) : 99999} + value={Units.kilogramToUser(totalCargoDesired)} + onBlur={(x) => { + if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) { + setTargetCargo(0, Units.userToKilogram(parseInt(x))); + } + }} + unit={massUnitForDisplay} + disabled={BoardingInProgress} + />
-
- -
- {/* TODO FIXME: Setting pax/cargo given desired ZFWCG, ZFW, total pax, total cargo */} -
- + +
+ +
+ {displayZfw ? t('Ground.Payload.ZFW') : t('Ground.Payload.GW')} + + {(displayZfw + ? ( + +
+ { + if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) processZfw(Units.userToKilogram(parseInt(x))); + }} + unit={massUnitForDisplay} + disabled={BoardingInProgress} + />
- {/* - 0 ? maxPax : 999} - value={zfwCgMac.toFixed(2)} - onBlur={{(x) => processZfwCg(x)} +
+ ) + : ( + +
+ { + if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) processGw(Units.userToKilogram(parseInt(x))); + }} + unit={massUnitForDisplay} + disabled={BoardingInProgress} /> - */} +
+
+ ) + )} +
+ +
+
+
+ {t(displayZfw ? 'Ground.Payload.ZFWCG' : 'Ground.Payload.GWCG')} +
+
+ +
+
+
+ +
+ {/* TODO FIXME: Setting pax/cargo given desired ZFWCG, ZFW, total pax, total cargo */} +
+
- -
- -
+ {/* + 0 ? maxPax : 999} + value={zfwCgMac.toFixed(2)} + onBlur={{(x) => processZfwCg(x)} + /> + */} +
+ + + + + + + + - ); -}; +); diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadPage.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadPage.tsx index 8b6b509a75f..1e8900d959b 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadPage.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadPage.tsx @@ -3,7 +3,7 @@ /* eslint-disable max-len */ import React, { useState } from 'react'; -import { AirframeInfo, CabinInfo, FlypadInfo, PayloadType, Units, usePersistentProperty, useSimVar } from '@flybywiresim/fbw-sdk'; +import { AirframeInfo, AirframeType, CabinInfo, FlypadInfo, PayloadType, Units, usePersistentProperty, useSimVar } from '@flybywiresim/fbw-sdk'; import { useAppSelector, isSimbriefDataLoaded, getMaxPax, getMaxCargo } from '@flybywiresim/flypad'; import { A380Payload } from './WideBody/A380Payload'; import { A320Payload } from './NarrowBody/A320Payload'; @@ -51,8 +51,8 @@ export const PayloadPage = () => { const airframeInfo = useAppSelector((state) => state.config.airframeInfo); const cabinInfo = useAppSelector((state) => state.config.cabinInfo); - switch (flypadInfo.type) { - case PayloadType.DoubleDeckPassengerOps: + switch (airframeInfo.variant) { + case AirframeType.A380_842: return ( { setBoardingRate={setBoardingRate} /> ); - case PayloadType.SingleDeckPassengerOps: - case PayloadType.Default: + case AirframeType.A320_251N: default: return ( = ({ seatMap, desiredFlags, activeFlags, canvasX, canvasY, theme, isMainDeck, onClickSeat }) => { +export const SeatMapWidget: React.FC = ({ payloadSeatDisplay, seatMap, desiredFlags, activeFlags, width, height, canvasX, canvasY, theme, isMainDeck, onClickSeat }) => { const canvasRef = useRef(null); const [ctx, setCtx] = useState(null); @@ -77,10 +79,10 @@ export const SeatMapWidget: React.FC = ({ seatMap, desiredFlags, a } } if (row !== 0 || station !== 0) { - xOff += (SeatConstants[seatType].padX + SeatConstants[seatType].len); + xOff += (payloadSeatDisplay[seatType].padX + payloadSeatDisplay[seatType].len); } return xOff; - }, [ctx]); + }, [payloadSeatDisplay, ctx]); const addYOffsetSeat = useMemo(() => (yOff: number, station: number, row: number, seat: number) => { if (seatMap[station].rows[row].yOffset !== undefined @@ -90,10 +92,10 @@ export const SeatMapWidget: React.FC = ({ seatMap, desiredFlags, a } const seatType = seatMap[station].rows[row].seats[seat].type; if (seat !== 0) { - yOff += (SeatConstants[seatType].padY + SeatConstants[seatType].wid); + yOff += (payloadSeatDisplay[seatType].padY + payloadSeatDisplay[seatType].wid); } return yOff; - }, [ctx]); + }, [payloadSeatDisplay, ctx]); const draw = () => { const currDeck = isMainDeck ? 0 : 1; @@ -126,9 +128,9 @@ export const SeatMapWidget: React.FC = ({ seatMap, desiredFlags, a if (!xYMap[station]) { xYMap[station] = []; } - xYMap[station][seatId] = [x + SeatConstants[seatsInfo[seat].type].imageX / 2, yOff + SeatConstants[seatsInfo[seat].type].imageY / 2, deck]; + xYMap[station][seatId] = [x + payloadSeatDisplay[seatsInfo[seat].type].imageX / 2, yOff + payloadSeatDisplay[seatsInfo[seat].type].imageY / 2, deck]; setXYMap(xYMap); - drawSeat(x, yOff, seatsInfo[seat].type, SeatConstants[seatsInfo[seat].type].imageX, SeatConstants[seatsInfo[seat].type].imageY, station, seatId++); + drawSeat(x, yOff, seatsInfo[seat].type, payloadSeatDisplay[seatsInfo[seat].type].imageX, payloadSeatDisplay[seatsInfo[seat].type].imageY, station, seatId++); } }; @@ -226,9 +228,6 @@ export const SeatMapWidget: React.FC = ({ seatMap, desiredFlags, a useEffect(() => { const context = canvasRef.current.getContext('2d'); - - const width = CanvasConst.width; - const height = CanvasConst.height; let ratio = 1; ratio = window.devicePixelRatio; canvasRef.current.width = width * ratio; diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx index f8017296629..523832de81b 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx @@ -4,12 +4,11 @@ /* eslint-disable max-len */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { AirplaneFill, CloudArrowDown } from 'react-bootstrap-icons'; -import { SeatFlags, Units, usePersistentNumberProperty, usePersistentProperty, useSeatFlags, useSimVar } from '@flybywiresim/fbw-sdk'; +import { CargoStationInfo, PaxStationInfo, SeatFlags, Units, usePersistentNumberProperty, usePersistentProperty, useSeatFlags, useSimVar } from '@flybywiresim/fbw-sdk'; import { setPayloadImported, setDisplayPaxMainDeck, t, useAppDispatch, TooltipWrapper, PromptModal, useModals, SelectGroup, SelectItem, Card, A380SeatOutlineBg, A380SeatOutlineUpperBg, useAppSelector } from '@flybywiresim/flypad'; import { BoardingInput, MiscParamsInput, PayloadInputTable } from '../PayloadElements'; import { CargoWidget } from './CargoWidget'; import { ChartWidget } from '../Chart/ChartWidget'; -import { CargoStationInfo, PaxStationInfo } from '../Seating/Constants'; import { SeatMapWidget } from '../Seating/SeatMapWidget'; import { PayloadProps } from '../PayloadPage'; @@ -216,7 +215,7 @@ export const A380Payload: React.FC = ({ fillStation(i, parseFloat(Number((Math.ceil((seatMap[i].capacity / maxPax) * 1e2) / 1e2).toExponential(2)).toPrecision(3)), numOfPax); } fillStation(0, 1, paxRemaining); - }, [maxPax, ...seatMap, totalPaxDesired]); + }, [maxPax, seatMap, totalPaxDesired]); const setTargetCargo = useCallback((numberOfPax: number, freight: number, perBagWeight: number = paxBagWeight) => { const bagWeight = numberOfPax * perBagWeight; @@ -224,7 +223,7 @@ export const A380Payload: React.FC = ({ let remainingWeight = loadableCargoWeight; - async function fillCargo(station: number, percent: number, loadableCargoWeight: number) { + function fillCargo(station: number, percent: number, loadableCargoWeight: number) { const c = Math.round(percent * loadableCargoWeight); remainingWeight -= c; setCargoDesired[station](c); @@ -234,7 +233,7 @@ export const A380Payload: React.FC = ({ fillCargo(i, cargoMap[i].weight / maxCargo, loadableCargoWeight); } fillCargo(0, 1, remainingWeight); - }, [maxCargo, ...cargoMap, ...cargoDesired, paxBagWeight]); + }, [maxCargo, cargoMap, ...cargoDesired, paxBagWeight]); const processZfw = useCallback((newZfw) => { let paxCargoWeight = newZfw - emptyWeight; @@ -265,7 +264,7 @@ export const A380Payload: React.FC = ({ }, [emptyWeight, paxWeight, paxBagWeight, maxPax, maxCargo, gw, zfw]); const onClickCargo = useCallback((cargoStation, e) => { - if (gsxPayloadSyncEnabled === 1 && boardingStarted) { + if (gsxInProgress() || boardingStarted) { return; } const cargoPercent = Math.min(Math.max(0, e.nativeEvent.offsetX / cargoMap[cargoStation].progressBarWidth), 1); @@ -273,7 +272,7 @@ export const A380Payload: React.FC = ({ }, [cargoMap]); const onClickSeat = useCallback((stationIndex: number, seatId: number) => { - if (gsxPayloadSyncEnabled === 1 && boardingStarted) { + if (gsxInProgress() || boardingStarted) { return; } @@ -452,7 +451,7 @@ export const A380Payload: React.FC = ({ ); } - if (gsxPayloadSyncEnabled === 1) { + if (gsxInProgress() || boardingStarted) { if (boardingStarted) { setShowSimbriefButton(false); return; @@ -503,7 +502,6 @@ export const A380Payload: React.FC = ({ return [base, primary, secondary]; }, [theme]); - if (airframeInfo === null) return (<>); return (
@@ -515,7 +513,19 @@ export const A380Payload: React.FC = ({ {!displayPaxMainDeck && ( )} - +
@@ -570,7 +580,7 @@ export const A380Payload: React.FC = ({
= ({ width={525} height={511} envelope={airframeInfo.designLimits.performanceEnvelope} - limits={flypadInfo.chartLimits} + limits={flypadInfo.payloadChartLimits} cg={boardingStarted ? Math.round(gwCgMac * 100) / 100 : Math.round(desiredGwCgMac * 100) / 100} gw={boardingStarted ? Math.round(gw) : Math.round(gwDesired)} mldwCg={boardingStarted ? Math.round(gwCgMac * 100) / 100 : Math.round(desiredGwCgMac * 100) / 100} diff --git a/fbw-common/src/systems/instruments/src/react/bitFlags.tsx b/fbw-common/src/systems/instruments/src/react/bitFlags.tsx index 0128cdc0d61..1127785c90d 100644 --- a/fbw-common/src/systems/instruments/src/react/bitFlags.tsx +++ b/fbw-common/src/systems/instruments/src/react/bitFlags.tsx @@ -1,5 +1,5 @@ import { useCallback, useMemo, useRef, useState } from 'react'; -import { SeatFlags } from '../../../shared/src'; +import { PaxStationInfo, SeatFlags } from '../../../shared/src'; import { useSimVarList } from './simVars'; import { useUpdate } from './hooks'; @@ -53,7 +53,7 @@ export const useSeatFlags = ( }; export const useSeatMap = ( - Loadsheet: any, + seatMap: PaxStationInfo[], ) : [ SeatFlags[], SeatFlags[], @@ -74,53 +74,51 @@ export const useSeatMap = ( const desiredUnits: string[] = []; const activeNames: string[] = []; const activeUnits: string[] = []; - Loadsheet.seatMap.forEach((station) => { - desiredNames.push(`L:${station.bitFlags}_DESIRED`); + seatMap.forEach((station) => { + desiredNames.push(`L:${station.simVar}_DESIRED`); desiredUnits.push('number'); - activeNames.push(`L:${station.bitFlags}`); + activeNames.push(`L:${station.simVar}`); activeUnits.push('number'); }); return [desiredNames, desiredUnits, activeNames, activeUnits]; - }, [Loadsheet]); + }, [seatMap]); - const [desiredBitVars] = useSimVarList(desiredVarNames, desiredVarUnits); - const [activeBitVars] = useSimVarList(activeVarNames, activeVarUnits); + const [desiredBitVars] = useSimVarList(desiredVarNames, desiredVarUnits, 379); + const [activeBitVars] = useSimVarList(activeVarNames, activeVarUnits, 379); const setActiveFlags = useCallback((value: SeatFlags, index: number) => { - SimVar.SetSimVarValue(`L:${Loadsheet.seatMap[index].bitFlags}`, 'string', value.toString()).catch(console.error).then(); - }, [Loadsheet]); + SimVar.SetSimVarValue(`L:${seatMap[index].simVar}`, 'string', value.toString()).catch(console.error).then(); + }, [seatMap]); const setDesiredFlags = useCallback((value: SeatFlags, index: number) => { - SimVar.SetSimVarValue(`L:${Loadsheet.seatMap[index].bitFlags}_DESIRED`, 'string', value.toString()).catch(console.error).then(); - }, [Loadsheet]); + SimVar.SetSimVarValue(`L:${seatMap[index].simVar}_DESIRED`, 'string', value.toString()).catch(console.error).then(); + }, [seatMap]); + + const stationSizes = useMemo(() => seatMap.map((station) => { + let stationSize = 0; + station.rows.forEach((row) => { + row.seats.forEach(() => { + stationSize++; + }); + }); + return stationSize; + }), [seatMap]); const desiredFlags = useMemo(() => { const flags: SeatFlags[] = []; - Loadsheet.seatMap.forEach((station, index) => { - let stationSize = 0; - station.rows.forEach((row) => { - row.seats.forEach(() => { - stationSize++; - }); - }); - flags[index] = new SeatFlags(desiredBitVars[index], stationSize); + seatMap.forEach((_station, index) => { + flags[index] = new SeatFlags(desiredBitVars[index], stationSizes[index]); }); return flags; - }, [desiredBitVars, ...desiredBitVars]); + }, [...desiredBitVars, stationSizes]); const activeFlags = useMemo(() => { const flags: SeatFlags[] = []; - Loadsheet.seatMap.forEach((station, index) => { - let stationSize = 0; - station.rows.forEach((row) => { - row.seats.forEach(() => { - stationSize++; - }); - }); - flags[index] = new SeatFlags(activeBitVars[index], stationSize); + seatMap.forEach((_station, index) => { + flags[index] = new SeatFlags(activeBitVars[index], stationSizes[index]); }); return flags; - }, [activeBitVars, ...activeBitVars]); + }, [...activeBitVars, stationSizes]); return [ desiredFlags, diff --git a/fbw-common/src/systems/instruments/src/react/simVars.tsx b/fbw-common/src/systems/instruments/src/react/simVars.tsx index 52b3130c9d8..068cc18eab1 100644 --- a/fbw-common/src/systems/instruments/src/react/simVars.tsx +++ b/fbw-common/src/systems/instruments/src/react/simVars.tsx @@ -129,34 +129,21 @@ export const useSimVarList = ( if (delta >= refreshInterval) { lastUpdate.current = Date.now(); - names.forEach((name, index) => { - stateList[index] = SimVar.GetSimVarValue(name, units[index]); - }); - setStateList(stateList); + setStateList((prevStateList) => prevStateList.map((value, index) => SimVar.GetSimVarValue(names[index], units[index]))); } - }, [ - names, ...names, - units, ...units, - refreshInterval, - ]); + }, [names, units, refreshInterval]); useUpdate(updateCallback); const setter = useCallback((valuesOrSetter: any | SimVarSetter) => { - const executedValues = typeof valuesOrSetter === 'function' ? valuesOrSetter(stateList) : valuesOrSetter; - - executedValues.forEach((executedValue, index) => { - SimVar.SetSimVarValue(names[index], units[index], executedValue); - stateList[index] = executedValue; + setStateList((prevStateList) => { + const executedValues = typeof valuesOrSetter === 'function' ? valuesOrSetter(prevStateList) : valuesOrSetter; + executedValues.forEach((executedValue, index) => { + SimVar.SetSimVarValue(names[index], units[index], executedValue); + }); + return executedValues; }); - setStateList(stateList); - - return stateList; - }, [ - names, ...names, - units, ...units, - ...stateList, stateList, - ]); + }, [names, units]); return [stateList, setter]; }; diff --git a/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts b/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts index 32d6844306c..0116811f5f6 100644 --- a/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts +++ b/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts @@ -55,8 +55,9 @@ export class UniversalConfigProvider { const json = await this.fetchVFSJson5(aircraft, variant, '', 'flypad-payload'); this.flypadInfo = ( { - type: json._type, - chartLimits: json.chartLimits, + payloadChartLimits: json.chartLimits, + payloadPlaneCanvas: json._canvas, + payloadSeatDisplay: json._seatDisplay, } ); diff --git a/fbw-common/src/systems/shared/src/unifiedConfig.ts b/fbw-common/src/systems/shared/src/unifiedConfig.ts index 350e7de8fcd..252f6018bc7 100644 --- a/fbw-common/src/systems/shared/src/unifiedConfig.ts +++ b/fbw-common/src/systems/shared/src/unifiedConfig.ts @@ -41,19 +41,29 @@ export interface AirframePerformanceEnvelope { flight: number[][]; } -export enum PayloadType { - Default = 0, - SingleDeckPassengerOps = 1, - DoubleDeckPassengerOps = 2 -} /** - * Contains the flypad-payload.json file's information in a structured way. + * Contains the flypad-*.json files' information in a structured way. */ export interface FlypadInfo { - type: PayloadType; - chartLimits: PayloadChartLimits; + payloadPlaneCanvas: PayloadPlaneCanvas; + payloadChartLimits: PayloadChartLimits; + payloadSeatDisplay: PayloadSeatDisplay[]; +} +export interface PayloadPlaneCanvas { + width: number; + height: number; + canvasX: number; + canvasY: number; } +export interface PayloadSeatDisplay { + len: number; + wid: number; + padX: number; + padY: number; + imageX: number; + imageY: number; +} export interface PayloadChartLimits { weight: ChartLimitsWeights; cg: ChartLimitsCG;