feat(scenes): add scene darkness reveal and fix project reopen crash
Add darkenScene with Opening brush in presentation, persist reveal strokes per scene during a session, and close projects properly on return to home. Harden dnd asset streaming to avoid Windows main-process crashes when reopening projects. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -623,6 +623,7 @@ export function EditorApp() {
|
||||
previewAssetType={sc?.previewAssetType ?? null}
|
||||
previewVideoAutostart={sc?.previewVideoAutostart ?? false}
|
||||
previewRotationDeg={sc?.previewRotationDeg ?? 0}
|
||||
darkenScene={sc?.darkenScene ?? false}
|
||||
previewBusy={previewBusy}
|
||||
mediaAssets={sceneMediaAssets}
|
||||
audioRefs={sceneAudioRefs}
|
||||
@@ -632,6 +633,9 @@ export function EditorApp() {
|
||||
onPreviewVideoAutostartChange={(next) =>
|
||||
void actions.updateScene(sid, { previewVideoAutostart: next })
|
||||
}
|
||||
onDarkenSceneChange={(next) =>
|
||||
void actions.updateScene(sid, { darkenScene: next })
|
||||
}
|
||||
onTitleChange={(title) => void actions.updateScene(sid, { title })}
|
||||
onDescriptionChange={(description) =>
|
||||
void actions.updateScene(sid, { description })
|
||||
@@ -1681,11 +1685,13 @@ type SceneInspectorProps = {
|
||||
previewAssetType: 'image' | 'video' | null;
|
||||
previewVideoAutostart: boolean;
|
||||
previewRotationDeg: 0 | 90 | 180 | 270;
|
||||
darkenScene: boolean;
|
||||
previewBusy: boolean;
|
||||
mediaAssets: MediaAsset[];
|
||||
audioRefs: SceneAudioRef[];
|
||||
onAudioRefsChange: (next: SceneAudioRef[]) => void;
|
||||
onPreviewVideoAutostartChange: (next: boolean) => void;
|
||||
onDarkenSceneChange: (next: boolean) => void;
|
||||
onTitleChange: (v: string) => void;
|
||||
onDescriptionChange: (v: string) => void;
|
||||
onImportPreview: () => void;
|
||||
@@ -1788,11 +1794,13 @@ function SceneInspector({
|
||||
previewAssetType,
|
||||
previewVideoAutostart,
|
||||
previewRotationDeg,
|
||||
darkenScene,
|
||||
previewBusy,
|
||||
mediaAssets,
|
||||
audioRefs,
|
||||
onAudioRefsChange,
|
||||
onPreviewVideoAutostartChange,
|
||||
onDarkenSceneChange,
|
||||
onTitleChange,
|
||||
onDescriptionChange,
|
||||
onImportPreview,
|
||||
@@ -1877,6 +1885,19 @@ function SceneInspector({
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
{previewAssetId && previewAssetType === 'image' ? (
|
||||
<>
|
||||
<div className={styles.spacer6} />
|
||||
<label className={styles.checkboxLabel}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={darkenScene}
|
||||
onChange={(e) => onDarkenSceneChange(e.target.checked)}
|
||||
/>
|
||||
<span className={styles.spanSm}>{t('scene.darkenScene')}</span>
|
||||
</label>
|
||||
</>
|
||||
) : null}
|
||||
<div className={styles.spacer6} />
|
||||
<div className={styles.labelSm}>{t('scene.audio')}</div>
|
||||
<div className={styles.audioDrop}>
|
||||
|
||||
@@ -281,6 +281,7 @@ export const EDITOR_MESSAGES: Record<EditorLocale, Record<string, string>> = {
|
||||
'scene.change': 'Изменить',
|
||||
'scene.clear': 'Очистить',
|
||||
'scene.autostart': 'Автостарт',
|
||||
'scene.darkenScene': 'Затемнить сцену',
|
||||
'scene.rotate': 'Повернуть',
|
||||
'scene.audio': 'АУДИО СЦЕНЫ',
|
||||
'scene.removeTitle': 'Убрать из сцены',
|
||||
@@ -319,6 +320,8 @@ export const EDITOR_MESSAGES: Record<EditorLocale, Record<string, string>> = {
|
||||
'control.fire': 'Огонь',
|
||||
'control.water': 'Вода',
|
||||
'control.darkness': 'Тьма',
|
||||
'control.darknessControl': 'Управление затемнением',
|
||||
'control.explorerBrush': 'Кисть Открытия',
|
||||
'control.lightning': 'Молния',
|
||||
'control.sunbeam': 'Луч света',
|
||||
'control.freeze': 'Заморозка',
|
||||
@@ -601,6 +604,7 @@ export const EDITOR_MESSAGES: Record<EditorLocale, Record<string, string>> = {
|
||||
'scene.change': 'Change',
|
||||
'scene.clear': 'Clear',
|
||||
'scene.autostart': 'Autostart',
|
||||
'scene.darkenScene': 'Darken scene',
|
||||
'scene.rotate': 'Rotate',
|
||||
'scene.audio': 'SCENE AUDIO',
|
||||
'scene.removeTitle': 'Remove from scene',
|
||||
@@ -639,6 +643,8 @@ export const EDITOR_MESSAGES: Record<EditorLocale, Record<string, string>> = {
|
||||
'control.fire': 'Fire',
|
||||
'control.water': 'Water',
|
||||
'control.darkness': 'Darkness',
|
||||
'control.darknessControl': 'Darkness control',
|
||||
'control.explorerBrush': 'Opening brush',
|
||||
'control.lightning': 'Lightning',
|
||||
'control.sunbeam': 'Sunbeam',
|
||||
'control.freeze': 'Freeze',
|
||||
|
||||
@@ -32,6 +32,7 @@ type Actions = {
|
||||
previewAssetType?: 'image' | 'video' | null;
|
||||
previewVideoAutostart?: boolean;
|
||||
previewRotationDeg?: 0 | 90 | 180 | 270;
|
||||
darkenScene?: boolean;
|
||||
settings?: Partial<Scene['settings']>;
|
||||
media?: Partial<Scene['media']>;
|
||||
layout?: { x: number; y: number };
|
||||
@@ -140,6 +141,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
};
|
||||
|
||||
const closeProject = async () => {
|
||||
await api.invoke(ipcChannels.project.close, {});
|
||||
setState((s) => ({ ...s, project: null, selectedSceneId: null }));
|
||||
await refreshProjects();
|
||||
};
|
||||
@@ -157,6 +159,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
previewAssetType: null,
|
||||
previewVideoAutostart: false,
|
||||
previewRotationDeg: 0,
|
||||
darkenScene: false,
|
||||
media: { videos: [], audios: [] },
|
||||
settings: { autoplayVideo: false, autoplayAudio: true, loopVideo: true, loopAudio: true },
|
||||
connections: [],
|
||||
@@ -212,6 +215,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
previewAssetType?: 'image' | 'video' | null;
|
||||
previewVideoAutostart?: boolean;
|
||||
previewRotationDeg?: 0 | 90 | 180 | 270;
|
||||
darkenScene?: boolean;
|
||||
settings?: Partial<Scene['settings']>;
|
||||
media?: Partial<Scene['media']>;
|
||||
layout?: { x: number; y: number };
|
||||
@@ -237,6 +241,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
...(patch.previewRotationDeg !== undefined
|
||||
? { previewRotationDeg: patch.previewRotationDeg }
|
||||
: null),
|
||||
...(patch.darkenScene !== undefined ? { darkenScene: patch.darkenScene } : null),
|
||||
...(patch.settings ? { settings: { ...scene.settings, ...patch.settings } } : null),
|
||||
...(patch.media ? { media: { ...scene.media, ...patch.media } } : null),
|
||||
layout: patch.layout ? { ...scene.layout, ...patch.layout } : scene.layout,
|
||||
|
||||
Reference in New Issue
Block a user