feat: scene traps, material legends, and scene editor window
Add trap overlays with session state, material legend editor/panel, and a dedicated scene editor window wired through IPC and project persistence. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,12 +27,15 @@ import { SceneDarknessOverlay } from '../shared/effects/SceneDarknessOverlay';
|
||||
import { useEffectsState } from '../shared/effects/useEffectsState';
|
||||
import { useSceneDarknessState } from '../shared/effects/useSceneDarknessState';
|
||||
import { DEFAULT_MATERIALS_OVERLAY_LAYOUT, DEFAULT_NPCS_OVERLAY_LAYOUT } from '../../shared/types';
|
||||
import { MaterialLegendPanel } from '../shared/materials/MaterialLegendPanel';
|
||||
import { MaterialOverlay } from '../shared/materials/MaterialOverlay';
|
||||
import { useMaterialsOverlayState } from '../shared/materials/useMaterialsOverlayState';
|
||||
import { NpcsSceneOverlay } from '../shared/npcs/NpcsSceneOverlay';
|
||||
import { useNpcsOverlayState } from '../shared/npcs/useNpcsOverlayState';
|
||||
import { SceneOverlayHost } from '../shared/sceneOverlay/SceneOverlayHost';
|
||||
import { useSceneViewState } from '../shared/sceneView/useSceneViewState';
|
||||
import { SceneTrapsOverlay } from '../shared/traps/SceneTrapsOverlay';
|
||||
import { useSceneTrapsState } from '../shared/traps/useSceneTrapsState';
|
||||
import { Button } from '../shared/ui/controls';
|
||||
import { Surface } from '../shared/ui/Surface';
|
||||
import { useAssetUrl } from '../shared/useAssetImageUrl';
|
||||
@@ -119,6 +122,7 @@ export function ControlApp() {
|
||||
const [fxState, fx] = useEffectsState();
|
||||
const [effectsSfxGainUi, setEffectsSfxGainUi] = useState(() => getEffectsSfxGain());
|
||||
const [sdState, sd] = useSceneDarknessState();
|
||||
const [sceneTraps, sceneTrapsApi] = useSceneTrapsState();
|
||||
const [sceneView, sceneViewApi] = useSceneViewState();
|
||||
const [sceneViewDraft, setSceneViewDraft] = useState<SceneViewCamera | null>(null);
|
||||
const [materialsOverlay, materialsApi] = useMaterialsOverlayState();
|
||||
@@ -1818,6 +1822,17 @@ export function ControlApp() {
|
||||
clearDraftFromPixi();
|
||||
}}
|
||||
/>
|
||||
{previewContentRect ? (
|
||||
<SceneTrapsOverlay
|
||||
traps={currentScene?.traps ?? []}
|
||||
session={sceneTraps}
|
||||
viewport={previewContentRect}
|
||||
mode="control"
|
||||
onReveal={(trapId) => void sceneTrapsApi.dispatch({ kind: 'reveal', trapId })}
|
||||
onActivate={(trapId) => void sceneTrapsApi.dispatch({ kind: 'activate', trapId })}
|
||||
onDisarm={(trapId) => void sceneTrapsApi.dispatch({ kind: 'disarm', trapId })}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
) : null}
|
||||
{(() => {
|
||||
@@ -1893,6 +1908,28 @@ export function ControlApp() {
|
||||
onLayoutChange={(layout) => {
|
||||
void materialsApi.dispatch({ kind: 'layout.set', layout });
|
||||
}}
|
||||
legendMarkers={
|
||||
activeMaterial.legend?.enabled
|
||||
? (activeMaterial.legend.markers ?? [])
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
{showMaterial && activeMaterial?.legend?.enabled ? (
|
||||
<MaterialLegendPanel
|
||||
legend={activeMaterial.legend}
|
||||
layout={
|
||||
materialsOverlay?.legendLayout ?? {
|
||||
...DEFAULT_MATERIALS_OVERLAY_LAYOUT,
|
||||
cx: 0.82,
|
||||
cy: 0.5,
|
||||
scale: 0.85,
|
||||
}
|
||||
}
|
||||
editable
|
||||
onLayoutChange={(layout) => {
|
||||
void materialsApi.dispatch({ kind: 'legendLayout.set', layout });
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{showNpcs ? (
|
||||
|
||||
Reference in New Issue
Block a user