Ensure proper 2024

This commit is contained in:
Kilian Hofmann 2025-02-22 19:17:54 +01:00
parent eb3c96361a
commit 8d91bcbe74
8 changed files with 167 additions and 133 deletions

View File

@ -9,17 +9,21 @@ interface AppProps {
const App: FC<AppProps> = ({ type }) => {
const [contentOFP, setContentOFP] = useState('');
const [contentTLR, setContentTLR] = useState('');
const [page, setPage] = useState(0);
const [position, setPosition] = useState(1);
const [loading, setLoading] = useState(false);
const loopRef = useRef<number | undefined>(undefined);
useEffect(() => {
loopRef.current = setInterval(() => {
const flag = SimVar.GetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'bool');
const flag = SimVar.GetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'number');
const pos = SimVar.GetSimVarValue('L:KH_FE_FPLAN_BOARD', 'number');
if (flag) {
SimVar.SetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'bool', 0);
SimVar.SetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'number', 0);
getSB();
}
// does not rerender if prev === pos since state set with identical value
// does not trigger rerender
setPosition((prev) => (prev !== pos ? pos : prev));
}, 100);
return () => clearInterval(loopRef.current);
@ -31,12 +35,14 @@ const App: FC<AppProps> = ({ type }) => {
return JSON.parse(config).simBriefId as string;
} catch (e) {
console.error('Failed loading config.', e);
return null;
throw e;
}
};
const getSB = async () => {
try {
setLoading(true);
const res = await fetch(`https://www.simbrief.com/api/xml.fetcher.php?username=${sbID()}&json=1`);
if (res.ok) {
try {
@ -53,10 +59,13 @@ const App: FC<AppProps> = ({ type }) => {
}
} catch (e) {
console.error('FETCH ERR', e);
} finally {
setLoading(false);
}
};
const reloadSB = () => {
if (loading) return;
SimVar.SetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'bool', 1);
};
@ -66,20 +75,18 @@ const App: FC<AppProps> = ({ type }) => {
<OFP
content={contentOFP}
position={position}
page={page}
page={0}
loading={loading}
reload={reloadSB}
setPosition={setPosition}
setPage={setPage}
/>
)}
{type === 'tlr' && (
<TLR
content={contentTLR}
position={position}
page={page}
page={1}
loading={loading}
reload={reloadSB}
setPosition={setPosition}
setPage={setPage}
/>
)}
</>

View File

@ -10,21 +10,47 @@
padding-left: 7px;
padding-right: 7px;
.icon {
width: 30px;
margin-top: 6px;
}
&:hover:not([disabled]) {
background-color: var(--buttonHoverColor);
}
&.d180 {
transform: rotate(180deg);
.icon-container {
margin: 6px;
width: 30px;
height: 30px;
.icon {
width: 30px;
height: 30px;
&.d180 {
transform: rotate(180deg);
}
&.d90 {
transform: rotate(90deg);
}
}
.loader {
width: 30px;
height: 30px;
border: 5px solid black;
border-bottom-color: transparent;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
}
&.d90 {
transform: rotate(90deg);
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
}

View File

@ -1,22 +1,19 @@
import { Dispatch, FC, RefObject, SetStateAction } from 'react';
import { FC, RefObject } from 'react';
import './controls.scss';
interface ControlsProps {
containerRef: RefObject<HTMLDivElement | null>;
position: number;
page: number;
loading: boolean;
reload: () => void;
setPosition: Dispatch<SetStateAction<number>>;
setPage: Dispatch<SetStateAction<number>>;
}
const Controls: FC<ControlsProps> = ({ containerRef, position, page, reload, setPosition, setPage }) => {
const Controls: FC<ControlsProps> = ({ containerRef, position, page, loading, reload }) => {
const cycle = () => {
setPage((prev) => {
const _new = (prev + 1) % 2;
SimVar.SetSimVarValue('KH_FE_FPLAN_P1', 'bool', _new);
return _new;
});
if (page === 0) SimVar.SetSimVarValue('L:KH_FE_FPLAN_P1', 'number', 1);
if (page === 1) SimVar.SetSimVarValue('L:KH_FE_FPLAN_P1', 'number', 0);
};
const toTop = () => {
@ -26,43 +23,54 @@ const Controls: FC<ControlsProps> = ({ containerRef, position, page, reload, set
};
const switchPosition = () => {
setPosition((prev) => {
let _new = prev;
if (position === 1) _new = 2;
else if (position === 2) _new = 1;
SimVar.SetSimVarValue('KH_FE_FPLAN_BOARD', 'number', _new);
return _new;
});
let _position = SimVar.GetSimVarValue('L:KH_FE_FPLAN_BOARD', 'number');
if (_position === 1) _position = 2;
else if (_position === 2) _position = 1;
SimVar.SetSimVarValue('L:KH_FE_FPLAN_BOARD', 'number', _position);
};
return (
<div id="KH_CTRL">
{page === 1 && (
<div className="button" onClick={cycle}>
<img className="icon" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/get.png" />
<div className="icon-container">
<img className="icon" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/get.png" />
</div>
</div>
)}
<div className="button d90" onClick={toTop}>
<img className="icon" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/get.png" />
<div className="button" onClick={toTop}>
<div className="icon-container">
<img className="icon d90" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/get.png" />
</div>
</div>
<div className="button" onClick={reload}>
<img className="icon" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/cloud.png" />
<div className="icon-container">
{loading ? (
<span className="loader" />
) : (
<img className="icon" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/cloud.png" />
)}
</div>
</div>
<div className="button" onClick={switchPosition}>
<img
className="icon"
src={
position === 1
? '/Pages/VCockpit/Instruments/FSS_B727/KH_FE_FPLAN/assets/img/compass.png'
: position === 2
? '/Pages/VCockpit/Instruments/FSS_B727/KH_FE_FPLAN/assets/img/wrench.png'
: ''
}
/>
<div className="icon-container">
<img
className="icon"
src={
position === 1
? '/Pages/VCockpit/Instruments/FSS_B727/KH_FE_FPLAN/assets/img/compass.png'
: position === 2
? '/Pages/VCockpit/Instruments/FSS_B727/KH_FE_FPLAN/assets/img/wrench.png'
: ''
}
/>
</div>
</div>
{page === 0 && (
<div className="button d180" onClick={cycle}>
<img className="icon" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/get.png" />
<div className="button" onClick={cycle}>
<div className="icon-container">
<img className="icon d180" src="/Pages/VCockpit/Instruments/FSS_B727/EFB/Images/get.png" />
</div>
</div>
)}
</div>

View File

@ -1,20 +1,21 @@
import { createRef, Dispatch, FC, SetStateAction, useEffect } from 'react';
import { createRef, FC, useEffect } from 'react';
import Controls from '../controls/controls';
interface TLRProps {
content: string;
position: number;
page: number;
loading: boolean;
reload: () => void;
setPosition: Dispatch<SetStateAction<number>>;
setPage: Dispatch<SetStateAction<number>>;
}
const OFP: FC<TLRProps> = ({ content, position, page, reload, setPosition, setPage }) => {
const OFP: FC<TLRProps> = ({ content, position, page, loading, reload }) => {
const containerRef = createRef<HTMLDivElement>();
const defineDragScroll = (horizontalScroll = true, verticalScroll = true) => {
if (!containerRef.current) return;
if (!containerRef.current) return () => {};
const refCopy = containerRef.current;
let pos = { top: 0, left: 0, x: 0, y: 0 };
@ -53,25 +54,22 @@ const OFP: FC<TLRProps> = ({ content, position, page, reload, setPosition, setPa
};
containerRef.current.addEventListener('mousedown', mouseDownHandler);
return () => {
refCopy.removeEventListener('mousedown', mouseDownHandler);
};
};
useEffect(() => {
defineDragScroll();
}, [containerRef.current]);
return defineDragScroll();
});
return (
<>
<div ref={containerRef} id="KH_FE_FPLAN" className="p2">
<div id="OFP" dangerouslySetInnerHTML={{ __html: content }} />
</div>
<Controls
containerRef={containerRef}
position={position}
page={page}
reload={reload}
setPosition={setPosition}
setPage={setPage}
/>
<Controls containerRef={containerRef} position={position} page={page} loading={loading} reload={reload} />
</>
);
};

View File

@ -1,16 +1,15 @@
import { createRef, Dispatch, FC, SetStateAction, useEffect } from 'react';
import { createRef, FC, useEffect } from 'react';
import Controls from '../controls/controls';
interface TLRProps {
content: string;
position: number;
page: number;
loading: boolean;
reload: () => void;
setPosition: Dispatch<SetStateAction<number>>;
setPage: Dispatch<SetStateAction<number>>;
}
const TLR: FC<TLRProps> = ({ content, position, page, reload, setPosition, setPage }) => {
const TLR: FC<TLRProps> = ({ content, position, page, loading, reload }) => {
const containerRef = createRef<HTMLDivElement>();
const defineDragScroll = (horizontalScroll = true, verticalScroll = true) => {
@ -68,14 +67,7 @@ const TLR: FC<TLRProps> = ({ content, position, page, reload, setPosition, setPa
</div>
</div>
</div>
<Controls
containerRef={containerRef}
position={position}
page={page}
reload={reload}
setPosition={setPosition}
setPage={setPage}
/>
<Controls containerRef={containerRef} position={position} page={page} loading={loading} reload={reload} />
</>
);
};

View File

@ -4,8 +4,8 @@
/// <reference types="@microsoft/msfs-types/js/simvar" />
import { createRoot } from 'react-dom/client';
import App from './App';
import './index.scss';
class KH_FE_FPLAN extends BaseInstrument {
@ -37,16 +37,6 @@ class KH_FE_FPLAN extends BaseInstrument {
const root = createRoot(container);
root.render(<App type={type} />);
}
/*
FSComponent.render(
<>
{type === 'ofp' && <OFP content={this.contentOFP} position={this.position} reload={this.reloadSB} />}
{type === 'tlr' && <TLR content={this.contentTLR} position={this.position} reload={this.reloadSB} />}
</>,
document.getElementById('root')
);
*/
}
}

View File

@ -35,93 +35,75 @@ pixel_size = 183, 149
texture = $CIVA_Screen_3
htmlgauge00 = FSS_B727/CIVA/CIVAScreen3.html, 0, 0, 183, 149
; KHOFMANN START
# MSFS 2024
[VCockpit06]
background_color = 0,0,0
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $KH_FE_FPLAN_P1
htmlgauge00= FSS_B727/KH_FE_FPLAN/index.html?type=ofp, 0, 0, 840, 1188
texture = $EFB_CLIPBOARD_Screen_6
htmlgauge00 = FSS_B727/EFB/EFBCharts.html, 0, 0, 840, 1188
emissive = 0
[VCockpit07]
background_color = 0,0,0
size_mm = 210, 297
pixel_size = 840, 1188
texture = $KH_FE_FPLAN_P2
htmlgauge00= FSS_B727/KH_FE_FPLAN/index.html?type=tlr, 0, 0, 840, 1188
emissive = 0
; KHOFMANN END
# MSFS 2024
#[VCockpit08]
#size_mm = 840, 1188
#pixel_size = 840, 1188
#texture = $EFB_CLIPBOARD_Screen_6
#htmlgauge00 = FSS_B727/EFB/EFBCharts.html, 0, 0, 840, 1188
#emissive = 0
[VCockpit09]
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $EFB_CLIPBOARD_Screen_1
htmlgauge00 = FSS_B727/EFB/EFBLanding.html, 0, 0, 840, 1188
emissive = 0
[VCockpit10]
[VCockpit08]
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $EFB_CLIPBOARD_Screen_2
htmlgauge00 = FSS_B727/EFB/EFBFlight.html, 0, 0, 840, 1188
emissive = 0
[VCockpit11]
[VCockpit09]
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $EFB_CLIPBOARD_Screen_3
htmlgauge00 = FSS_B727/EFB/EFBTakeoff.html, 0, 0, 840, 1188
emissive = 0
[VCockpit12]
[VCockpit10]
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $EFB_CLIPBOARD_Screen_4
htmlgauge00 = FSS_B727/EFB/EFBPreflight.html, 0, 0, 840, 1188
emissive = 0
[VCockpit13]
[VCockpit11]
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $EFB_CLIPBOARD_Screen_5
htmlgauge00 = FSS_B727/EFB/EFBOptions.html, 0, 0, 840, 1188
emissive = 0
[VCockpit14]
[VCockpit12]
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $EFB_CLIPBOARD_Screen_7
htmlgauge00 = FSS_B727/EFB/EFBAircraft.html, 0, 0, 840, 1188
emissive = 0
[VCockpit15]
[VCockpit13]
size_mm = 620, 610
pixel_size = 620, 610
texture = $STBY_ARTIFICIAL_HORIZON_Ball
htmlgauge00 = NavSystems/AS1000_BackupDisplay/Attitude/AS1000_AttitudeBackup.html, 0,0, 620, 610
[VCockpit16]
[VCockpit14]
size_mm = 870, 860
pixel_size = 870, 860
texture = $artificial_horizon_screen_1
htmlgauge00 = FSS_B727/Attitude/AS1000_AttitudeBackup.html, 0,0, 870, 860
[VCockpit17]
[VCockpit15]
size_mm = 870, 860
pixel_size = 870, 860
texture = $artificial_horizon_screen_2
htmlgauge00 = FSS_B727/Attitude/AS1000_AttitudeBackup.html, 0,0, 870, 860
[VCockpit18]
[VCockpit16]
Background_color = 0,0,0
size_mm = 650,768
visible = 0
@ -129,7 +111,7 @@ pixel_size = 650,768
texture = $GTN750_screen
htmlgauge00= FSS_B727/pms50_gtn750_int/gtn750_int.html, 0, 0, 650,768
[VCockpit19]
[VCockpit17]
Background_color = 0,0,0
size_mm = 650,290
visible = 0
@ -137,75 +119,95 @@ pixel_size = 650,290
texture = $GTN650_screen
htmlgauge00= FSS_B727/pms50_gtn750_int/gtn650_int.html?index=2, 0, 0, 650,290
[VCockpit20]
[VCockpit18]
size_mm=0,0
pixel_size=0,0
texture=NO_TEXTURE
background_color=42,42,40
htmlgauge00= FSS_B727/WT/v2/WTT1.html, 0,0,0,0
[VCockpit21]
[VCockpit19]
size_mm=0,0
pixel_size=0,0
texture=NO_TEXTURE
background_color=42,42,40
htmlgauge00= FSS_B727/WT/v2/WTT2.html, 0,0,0,0
[VCockpit22]
[VCockpit20]
size_mm = 836, 646
pixel_size = 0, 0
texture = $GNSXLS_Screen
htmlgauge00= FSS_B727/GNSXLS/GNSXLS.html, 0, 0, 836, 646
[VCockpit23]
[VCockpit21]
size_mm = 660, 1420
pixel_size = 0, 0
texture = $IPHONE_Screen
htmlgauge00= FSS_B727/CrewCoordination/CrewCoordination.html, 0, 0, 660, 1420
[VCockpit24]
[VCockpit22]
size_mm = 650,768
pixel_size = 650,768
texture = $SCREEN_TDSGTNXI750
background_color=0,0,0
htmlgauge00=WasmInstrument/WasmInstrument.html?wasm_module=Gauge/TDSGTNXiGaugeModule.wasm&wasm_gauge=GTNXI750U1, 0,0,650,768
[VCockpit25]
[VCockpit23]
size_mm = 378, 320
pixel_size = 378, 320
texture = $VHFCOMM_Screen_1
htmlgauge00= FSS_B727/RadioScreens/RadioScreens.html?index=1&type=com, 0, 0, 378, 320
[VCockpit26]
[VCockpit24]
size_mm = 378, 320
pixel_size = 378, 320
texture = $VHFCOMM_Screen_2
htmlgauge00= FSS_B727/RadioScreens/RadioScreens.html?index=2&type=com, 0, 0, 378, 320
[VCockpit27]
[VCockpit25]
size_mm = 378, 320
pixel_size = 378, 320
texture = $NAV_Screen_1
htmlgauge00= FSS_B727/RadioScreens/RadioScreens.html?index=1&type=nav, 0, 0, 378, 320
[VCockpit28]
[VCockpit26]
size_mm = 378, 320
pixel_size = 378, 320
texture = $NAV_Screen_2
htmlgauge00= FSS_B727/RadioScreens/RadioScreens.html?index=2&type=nav, 0, 0, 378, 320
[VCockpit29]
[VCockpit27]
size_mm = 378, 320
pixel_size = 378, 320
texture = $ADF_Screen_1
htmlgauge00= FSS_B727/RadioScreens/RadioScreens.html?index=1&type=adf, 0, 0, 378, 320
[VCockpit30]
[VCockpit28]
size_mm = 378, 320
pixel_size = 378, 320
texture = $ADF_Screen_2
htmlgauge00= FSS_B727/RadioScreens/RadioScreens.html?index=2&type=adf, 0, 0, 378, 320
; KHOFMANN START
; MUST BE DECLARED INVERTED TO HOP THEY APPEAR IN GAME
; WHY, NO CLUE. ANNOYING AND NOT MENTIONED IN THE SDK WHATSOEVER
[VCockpit29]
background_color = 0,0,0
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $KH_FE_FPLAN_P2
htmlgauge00= FSS_B727/KH_FE_FPLAN/index.html?type=tlr, 0, 0, 840, 1188
emissive = 0
[VCockpit30]
background_color = 0,0,0
size_mm = 840, 1188
pixel_size = 840, 1188
texture = $KH_FE_FPLAN_P1
htmlgauge00= FSS_B727/KH_FE_FPLAN/index.html?type=ofp, 0, 0, 840, 1188
emissive = 0
; KHOFMANN END
[VPainting01]
size_mm = 2048,512
texture = $RegistrationNumber

View File

@ -1,4 +1,15 @@
# How to export a package
- `cd` into 2020 or 2024
- Run `pnpm install` and `pnpm prod` to build gauge
- Export from 2020 or 2024
- Export from MSFS
# Note on package files
Due to the `panel.cfg` differences in 2020 and 2024, two MSFS package XMLs
are included, one for 2020 and one for 2024.
It is to note that the 2024 package export will produce a model with broken
texture mappings due to the new 2024 texture format. The 2024 package is only
included to aid in development.
Exports should only ever be made from the 2020 XML in 2020. To create a 2024
package, the `panel.cfg` must be replaced and the `layout.json` remade
**after** the 2020 export process.
As it stands, the code is the same across both simulators.