feat: multi-material overlays, presentation guides, and release prebuilds
Align control/presentation with presentation screen rect and darkness z-order; sync window titles and session window cleanup. Pack Win/Mac/Linux with npmRebuild disabled and release-native-prep for classic-level and sharp. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { MaterialsZoomTool, NpcsZoomTool } from '../../../shared/types';
|
||||
import styles from '../materials/MaterialOverlay.module.css';
|
||||
|
||||
import { overlayRootStyle, type SceneOverlayViewport } from './overlayViewport';
|
||||
import { SceneOverlayViewContext } from './SceneOverlayViewContext';
|
||||
|
||||
export type SceneOverlayCloseAction = {
|
||||
@@ -14,6 +15,10 @@ export type SceneOverlayCloseAction = {
|
||||
type SceneOverlayHostProps = {
|
||||
/** Есть ли что показывать (материал и/или NPC). */
|
||||
active: boolean;
|
||||
/** Область картинки сцены (contain); координаты относительно родителя. */
|
||||
viewport?: SceneOverlayViewport | null;
|
||||
/** Рамка видимой области (предпросмотр пульта). */
|
||||
showViewportGuide?: boolean;
|
||||
zoomTool?: MaterialsZoomTool | NpcsZoomTool;
|
||||
onZoomAt?: (nx: number, ny: number, target: EventTarget | null) => void;
|
||||
closes?: readonly SceneOverlayCloseAction[];
|
||||
@@ -26,6 +31,8 @@ type SceneOverlayHostProps = {
|
||||
*/
|
||||
export function SceneOverlayHost({
|
||||
active,
|
||||
viewport = null,
|
||||
showViewportGuide = false,
|
||||
zoomTool = null,
|
||||
onZoomAt,
|
||||
closes = [],
|
||||
@@ -58,7 +65,7 @@ export function SceneOverlayHost({
|
||||
|
||||
const ctx = useMemo(() => ({ rootRef, view }), [view]);
|
||||
|
||||
if (!active) return null;
|
||||
if (!active && !showViewportGuide) return null;
|
||||
|
||||
const captureZoom = Boolean(zoomTool && onZoomAt);
|
||||
const zoomCursor =
|
||||
@@ -81,6 +88,7 @@ export function SceneOverlayHost({
|
||||
className={[styles.root, styles.hostHitThrough, captureZoom ? styles.captureZoom : '', zoomCursor]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
style={overlayRootStyle(viewport)}
|
||||
role="presentation"
|
||||
onClick={(e) => {
|
||||
if (!captureZoom || !onZoomAt) return;
|
||||
@@ -89,6 +97,7 @@ export function SceneOverlayHost({
|
||||
onZoomAt(nx, ny, e.target);
|
||||
}}
|
||||
>
|
||||
{showViewportGuide ? <div className={styles.viewportGuide} aria-hidden /> : null}
|
||||
<div className={styles.dim} />
|
||||
{children}
|
||||
{closes.length > 0 ? (
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
|
||||
export type SceneOverlayViewport = {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
};
|
||||
|
||||
export function overlayRootStyle(viewport: SceneOverlayViewport | null | undefined): CSSProperties | undefined {
|
||||
if (!viewport || viewport.w <= 0 || viewport.h <= 0) return undefined;
|
||||
return {
|
||||
left: viewport.x,
|
||||
top: viewport.y,
|
||||
width: viewport.w,
|
||||
height: viewport.h,
|
||||
right: 'auto',
|
||||
bottom: 'auto',
|
||||
overflow: 'hidden',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user