151 lines
7.9 KiB
TypeScript
151 lines
7.9 KiB
TypeScript
import {Checker,ColorField,ControlRow,Inspector,RangeControl,Select} from '@nodedc/ui-react';
|
||
import type {SceneSettings,PointColorMode,PointPalette} from './sceneSettings';
|
||
|
||
const colorModeOptions: Array<{ value: PointColorMode; label: string; description: string }> = [
|
||
{ value: "intensity", label: "Интенсивность", description: "Значение отражённого сигнала" },
|
||
{ value: "height", label: "Высота Z", description: "Градиент по вертикальной координате" },
|
||
{ value: "distance", label: "Расстояние", description: "Дальность точки от сенсора" },
|
||
{ value: "rgb", label: "RGB", description: "Цвет, если он присутствует в данных" },
|
||
{ value: "class", label: "Класс", description: "Категория внешнего модуля восприятия" },
|
||
];
|
||
|
||
const paletteOptions: Array<{ value: PointPalette; label: string; description: string }> = [
|
||
{ value: "turbo", label: "Turbo", description: "Контрастный спектральный градиент" },
|
||
{ value: "viridis", label: "Viridis", description: "Равномерный перцептивный градиент" },
|
||
{ value: "plasma", label: "Plasma", description: "Тёплый контрастный градиент" },
|
||
{ value: "grayscale", label: "Серый", description: "Монохромное отображение" },
|
||
{ value: "custom", label: "Свой цвет", description: "Один назначенный цвет" },
|
||
];
|
||
|
||
export function SceneDisplayControls({displayDraft,stageDisplayPatch,commitDisplayPatch,flushDisplaySettings,replayPresented=false}:{
|
||
displayDraft:SceneSettings;stageDisplayPatch:(patch:Partial<SceneSettings>)=>void;
|
||
commitDisplayPatch:(patch:Partial<SceneSettings>)=>void;flushDisplaySettings:()=>void;replayPresented?:boolean;
|
||
}) { return (
|
||
<Inspector
|
||
defaultOpen={["points"]}
|
||
singleOpen
|
||
sections={[
|
||
{
|
||
id: "points",
|
||
label: "Облако точек",
|
||
description: "Размер и способ окрашивания",
|
||
content: (
|
||
<div className="inspector-control-stack">
|
||
<div
|
||
className="scene-settings-commit-field"
|
||
onPointerUp={flushDisplaySettings}
|
||
onKeyUp={flushDisplaySettings}
|
||
onBlur={flushDisplaySettings}
|
||
>
|
||
<RangeControl
|
||
label="Размер точки"
|
||
value={displayDraft.pointSize}
|
||
min={0.5}
|
||
max={12}
|
||
step={0.5}
|
||
formatValue={(value) => `${value.toFixed(1)} пкс`}
|
||
onChange={(pointSize) => stageDisplayPatch({ pointSize })}
|
||
/>
|
||
</div>
|
||
<div className="scene-settings-commit-field" onBlur={flushDisplaySettings}>
|
||
<ControlRow label="Атрибут цвета">
|
||
<Select
|
||
variant="split"
|
||
label="Атрибут цвета"
|
||
value={displayDraft.colorMode}
|
||
options={colorModeOptions}
|
||
onChange={(colorMode) => stageDisplayPatch({ colorMode })}
|
||
/>
|
||
</ControlRow>
|
||
</div>
|
||
<div className="scene-settings-commit-field" onBlur={flushDisplaySettings}>
|
||
<ControlRow label="Палитра">
|
||
<Select
|
||
variant="split"
|
||
label="Палитра"
|
||
value={displayDraft.palette}
|
||
options={paletteOptions}
|
||
onChange={(palette) => stageDisplayPatch({ palette })}
|
||
/>
|
||
</ControlRow>
|
||
</div>
|
||
{displayDraft.palette === "custom" || displayDraft.colorMode === "class" ? (
|
||
<div
|
||
className="scene-settings-commit-field"
|
||
onPointerUp={flushDisplaySettings}
|
||
onKeyUp={flushDisplaySettings}
|
||
onBlur={flushDisplaySettings}
|
||
>
|
||
<ControlRow label="Цвет точек">
|
||
<ColorField
|
||
label="Цвет точек"
|
||
value={displayDraft.customColor}
|
||
onChange={(customColor) => stageDisplayPatch({ customColor })}
|
||
/>
|
||
</ControlRow>
|
||
</div>
|
||
) : null}
|
||
{replayPresented ? (
|
||
<p className="scene-window-note">
|
||
Первый новый режим читает индекс архивных точек. Следующие палитры
|
||
переключаются из подготовленного цветового кэша без переэкспорта геометрии.
|
||
</p>
|
||
) : null}
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
id: "history",
|
||
label: "Накопление и время",
|
||
description: "История облака и траектория",
|
||
content: (
|
||
<div className="inspector-control-stack">
|
||
<div
|
||
className="scene-settings-commit-field"
|
||
onPointerUp={flushDisplaySettings}
|
||
onKeyUp={flushDisplaySettings}
|
||
onBlur={flushDisplaySettings}
|
||
>
|
||
<RangeControl
|
||
label="Окно накопления"
|
||
value={displayDraft.accumulationSeconds}
|
||
min={0}
|
||
max={120}
|
||
step={1}
|
||
formatValue={(value) => (value === 0 ? "Только кадр" : `${value} с`)}
|
||
onChange={(accumulationSeconds) => stageDisplayPatch({ accumulationSeconds })}
|
||
/>
|
||
</div>
|
||
<div className="nodedc-field">
|
||
<span className="nodedc-field__description">Линия пути устройства в координатах сцены</span>
|
||
<Checker
|
||
checked={displayDraft.showTrajectory}
|
||
label="Показывать траекторию"
|
||
onChange={(showTrajectory) => commitDisplayPatch({ showTrajectory })}
|
||
/>
|
||
</div>
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
id: "scene",
|
||
label: "Окружение сцены",
|
||
description: "Сетка, подписи и камеры",
|
||
content: (
|
||
<div className="inspector-control-stack">
|
||
<Checker checked={displayDraft.showGrid} label="Сетка и оси" onChange={(showGrid) => commitDisplayPatch({ showGrid })} />
|
||
<div className="nodedc-field">
|
||
<span className="nodedc-field__description">Появятся после подключения семантических сущностей</span>
|
||
<Checker checked={false} disabled label="Подписи сущностей" onChange={() => undefined} />
|
||
</div>
|
||
<div className="nodedc-field">
|
||
<span className="nodedc-field__description">Камерный канал пока не подключён</span>
|
||
<Checker checked={false} disabled label="Области обзора камер" onChange={() => undefined} />
|
||
</div>
|
||
</div>
|
||
),
|
||
},
|
||
]}
|
||
/>
|
||
); }
|