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:
@@ -22,6 +22,8 @@ type MaterialOverlayProps = {
|
||||
onZoomAt?: (nx: number, ny: number) => void;
|
||||
/** Без собственного root/dim — внутри `SceneOverlayHost`. */
|
||||
embedded?: boolean;
|
||||
/** Маркеры легенды (норм. координаты картинки). */
|
||||
legendMarkers?: readonly { id: string; number: number; nx: number; ny: number }[];
|
||||
};
|
||||
|
||||
function RotateIcon() {
|
||||
@@ -99,6 +101,7 @@ export function MaterialOverlay({
|
||||
onLayoutChange,
|
||||
onZoomAt,
|
||||
embedded = false,
|
||||
legendMarkers,
|
||||
}: MaterialOverlayProps) {
|
||||
const url = useAssetUrl(assetId);
|
||||
const host = useSceneOverlayView();
|
||||
@@ -381,16 +384,23 @@ export function MaterialOverlay({
|
||||
src={url}
|
||||
alt=""
|
||||
draggable={false}
|
||||
style={{
|
||||
width: w,
|
||||
height: h,
|
||||
transform: 'translate(-50%, -50%)',
|
||||
}}
|
||||
onLoad={(e) => {
|
||||
const img = e.currentTarget;
|
||||
setNatural({ w: img.naturalWidth || 1, h: img.naturalHeight || 1 });
|
||||
}}
|
||||
/>
|
||||
{(legendMarkers ?? []).map((m) => (
|
||||
<div
|
||||
key={m.id}
|
||||
className={styles.legendMarker}
|
||||
style={{
|
||||
left: `${String(m.nx * 100)}%`,
|
||||
top: `${String(m.ny * 100)}%`,
|
||||
}}
|
||||
>
|
||||
{m.number}
|
||||
</div>
|
||||
))}
|
||||
{editable && !zoomTool
|
||||
? (['nw', 'ne', 'sw', 'se'] as const).map((corner) => (
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user