1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2025-present FERS Contributors (see AUTHORS.md).
11} from '@mui/material';
12import { Antenna, useScenarioStore } from '@/stores/scenarioStore';
13import { BufferedTextField, FileInput, NumberField } from './InspectorControls';
15interface AntennaInspectorProps {
19export function AntennaInspector({ item }: AntennaInspectorProps) {
20 const previewError = useScenarioStore(
21 (state) => state.antennaPreviewErrors[item.id]
23 const { updateItem, setAntennaPattern } = useScenarioStore.getState();
24 const handleChange = (path: string, value: unknown) =>
25 updateItem(item.id, path, value);
28 <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
36 onChange={(v) => handleChange('name', v)}
38 <FormControl fullWidth size="small">
39 <InputLabel>Pattern</InputLabel>
46 e.target.value as Antenna['pattern']
50 <MenuItem value="isotropic">Isotropic</MenuItem>
51 <MenuItem value="sinc">Sinc</MenuItem>
52 <MenuItem value="gaussian">Gaussian</MenuItem>
53 <MenuItem value="squarehorn">Square Horn</MenuItem>
54 <MenuItem value="parabolic">Parabolic</MenuItem>
55 <MenuItem value="xml">XML</MenuItem>
56 <MenuItem value="file">File (H5)</MenuItem>
61 value={item.efficiency}
62 emptyBehavior="revert"
63 onChange={(v) => handleChange('efficiency', v)}
66 label="Mesh Scale Multiplier"
67 value={item.meshScale ?? null}
69 onChange={(v) => handleChange('meshScale', v)}
71 {previewError && <Alert severity="error">{previewError}</Alert>}
73 {item.pattern === 'sinc' && (
77 value={item.alpha ?? null}
78 emptyBehavior="revert"
79 onChange={(v) => handleChange('alpha', v)}
83 value={item.beta ?? null}
84 emptyBehavior="revert"
85 onChange={(v) => handleChange('beta', v)}
89 value={item.gamma ?? null}
90 emptyBehavior="revert"
91 onChange={(v) => handleChange('gamma', v)}
95 {item.pattern === 'gaussian' && (
99 value={item.azscale ?? null}
100 emptyBehavior="revert"
101 onChange={(v) => handleChange('azscale', v)}
104 label="Elevation Scale"
105 value={item.elscale ?? null}
106 emptyBehavior="revert"
107 onChange={(v) => handleChange('elscale', v)}
111 {(item.pattern === 'squarehorn' ||
112 item.pattern === 'parabolic') && (
116 value={item.diameter ?? null}
117 emptyBehavior="revert"
118 onChange={(v) => handleChange('diameter', v)}
121 label="Design Frequency (Hz)"
122 value={item.design_frequency ?? null}
124 onChange={(v) => handleChange('design_frequency', v)}
129 {(item.pattern === 'xml' || item.pattern === 'file') && (
131 {/* TODO: Support authoring antenna XML in-app. That requires a real editor flow plus UI/store/schema
132 changes for antenna asset contents, rather than treating XML antennas as opaque filename-only assets. */}
135 value={item.filename}
136 onChange={(v) => handleChange('filename', v)}
139 name: 'Antenna Pattern',
141 item.pattern === 'xml' ? ['xml'] : ['h5'],
143 { name: 'All Files', extensions: ['*'] },