fix(materials): синхронизация легенды и маркеров на превью и презентации

Легенда и цифры на материале масштабируются от экрана игроков и не обрезаются жёлтой рамкой. Переключение сцен без записи project.json на диск.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-09-02 10:57:50 +08:00
parent ea718a26df
commit 153be98780
17 changed files with 531 additions and 128 deletions
+25 -16
View File
@@ -9,7 +9,7 @@ import { PixiEffectsOverlay } from './effects/PxiEffectsOverlay';
import { SceneDarknessOverlay } from './effects/SceneDarknessOverlay';
import { useEffectsState } from './effects/useEffectsState';
import { useSceneDarknessState } from './effects/useSceneDarknessState';
import { DEFAULT_MATERIALS_OVERLAY_LAYOUT, DEFAULT_NPCS_OVERLAY_LAYOUT } from '../../shared/types';
import { DEFAULT_MATERIALS_OVERLAY_LAYOUT, DEFAULT_NPCS_OVERLAY_LAYOUT, defaultLegendLayoutForMaterial } from '../../shared/types';
import { SceneGridOverlay } from './grid/SceneGridOverlay';
import { MaterialLegendPanel } from './materials/MaterialLegendPanel';
import { MaterialOverlay } from './materials/MaterialOverlay';
@@ -99,7 +99,7 @@ export function PresentationView({
return {
material,
layout: materialsOverlay?.layouts[id] ?? DEFAULT_MATERIALS_OVERLAY_LAYOUT,
legendLayout: materialsOverlay?.legendLayouts[id] ?? DEFAULT_MATERIALS_OVERLAY_LAYOUT,
legendLayout: materialsOverlay?.legendLayouts[id] ?? defaultLegendLayoutForMaterial(),
};
})
.filter((x): x is NonNullable<typeof x> => x !== null)
@@ -285,20 +285,29 @@ export function PresentationView({
contentRect ? (
<SceneDarknessOverlay state={sdState} overlayAlpha={1} viewport={contentRect} style={{ zIndex: 30 }} />
) : null}
<SceneOverlayHost active={activeMaterialItems.length > 0 || activeNpcItems.length > 0}>
{activeMaterialItems.map(({ material, layout, legendLayout }) => (
<React.Fragment key={material.id}>
<MaterialOverlay
embedded
assetId={material.assetId}
layout={layout}
materialId={material.id}
{...(material.legend?.enabled ? { legendMarkers: material.legend.markers ?? [] } : {})}
/>
{material.legend?.enabled ? (
<MaterialLegendPanel legend={material.legend} layout={legendLayout} />
) : null}
</React.Fragment>
<SceneOverlayHost
active={activeMaterialItems.length > 0 || activeNpcItems.length > 0}
legendLayer={
<>
{activeMaterialItems.map(({ material, legendLayout }) =>
material.legend?.enabled ? (
<MaterialLegendPanel key={material.id} legend={material.legend} layout={legendLayout} />
) : null,
)}
</>
}
>
{activeMaterialItems.map(({ material, layout }) => (
<MaterialOverlay
key={material.id}
embedded
assetId={material.assetId}
layout={layout}
materialId={material.id}
{...(material.legend?.enabled && (material.legend.markers?.length ?? 0) > 0
? { legendMarkers: material.legend.markers }
: {})}
/>
))}
{activeNpcItems.length > 0 ? <NpcsSceneOverlay embedded items={activeNpcItems} /> : null}
</SceneOverlayHost>