feat(control): инструмент «Маркер» на области видимости
Добавлена кисть маркера на пульте и презентации с настройками в панели эффектов; штрихи привязаны к жёлтой рамке, ластик и очистка работают с отдельным сессионным слоем. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
|
||||
import { EffectsStore, effectsDefaultTool } from './effects/effectsStore';
|
||||
import { SceneDarknessStore } from './effects/sceneDarknessStore';
|
||||
import { SceneMarkerStore } from './effects/sceneMarkerStore';
|
||||
import { SceneTrapsStore } from './sceneTraps/sceneTrapsStore';
|
||||
import { installIpcRouter, registerHandler, setLicenseAssert } from './ipc/router';
|
||||
import { LicenseService } from './license/licenseService';
|
||||
@@ -165,6 +166,7 @@ function installAppMenuForSession(): void {
|
||||
|
||||
const effectsStore = new EffectsStore();
|
||||
const sceneDarknessStore = new SceneDarknessStore();
|
||||
const sceneMarkerStore = new SceneMarkerStore();
|
||||
const sceneTrapsStore = new SceneTrapsStore();
|
||||
const sceneViewStore = new SceneViewStore();
|
||||
const videoStore = new VideoPlaybackStore();
|
||||
@@ -270,6 +272,13 @@ function emitSceneDarknessState(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function emitSceneMarkerState(): void {
|
||||
const state = sceneMarkerStore.getState();
|
||||
for (const win of BrowserWindow.getAllWindows()) {
|
||||
win.webContents.send(ipcChannels.sceneMarker.stateChanged, { state });
|
||||
}
|
||||
}
|
||||
|
||||
function emitSceneViewState(): void {
|
||||
const state = sceneViewStore.getState();
|
||||
for (const win of BrowserWindow.getAllWindows()) {
|
||||
@@ -357,6 +366,11 @@ function syncSceneDarknessForProject(project: Project): void {
|
||||
sceneDarknessStore.switchScene(cacheKey, enabled);
|
||||
}
|
||||
|
||||
function syncSceneMarkerForProject(project: Project): void {
|
||||
const cacheKey = project.currentGraphNodeId ?? project.currentSceneId ?? null;
|
||||
sceneMarkerStore.switchScene(cacheKey);
|
||||
}
|
||||
|
||||
function emitSceneTrapsState(): void {
|
||||
const state = sceneTrapsStore.getState();
|
||||
for (const win of BrowserWindow.getAllWindows()) {
|
||||
@@ -522,6 +536,7 @@ async function main() {
|
||||
registerHandler(ipcChannels.license.acceptEula, ({ version }) => licenseService.acceptEula(version));
|
||||
registerHandler(ipcChannels.windows.openMultiWindow, (req) => {
|
||||
sceneDarknessStore.resetSession();
|
||||
sceneMarkerStore.resetSession();
|
||||
sceneTrapsStore.resetSession();
|
||||
sceneTokensSessionStore.reset();
|
||||
tokenPathSessionStore.reset();
|
||||
@@ -540,12 +555,14 @@ async function main() {
|
||||
const project = projectStore.getOpenProject();
|
||||
if (project) {
|
||||
syncSceneDarknessForProject(project);
|
||||
syncSceneMarkerForProject(project);
|
||||
syncSceneTrapsForProject(project);
|
||||
seedTokenPathPlaybackForProject(project);
|
||||
} else {
|
||||
emitTokenPathSessionState();
|
||||
}
|
||||
emitSceneDarknessState();
|
||||
emitSceneMarkerState();
|
||||
emitSceneTrapsState();
|
||||
emitSceneTokensSessionState();
|
||||
emitSceneNpcTokensSessionState();
|
||||
@@ -674,10 +691,12 @@ async function main() {
|
||||
sceneNpcTokensSessionStore.reset();
|
||||
clearNpcMapSpawnDrag();
|
||||
scenePlayerTokensSessionStore.reset();
|
||||
syncSceneMarkerForProject(project);
|
||||
emitSceneViewState();
|
||||
emitSceneTokensSessionState();
|
||||
emitSceneNpcTokensSessionState();
|
||||
emitScenePlayerTokensSessionState();
|
||||
emitSceneMarkerState();
|
||||
emitSessionState();
|
||||
warmNpcsEditorWindow();
|
||||
return { project };
|
||||
@@ -689,6 +708,7 @@ async function main() {
|
||||
materialsOverlayStore.clear();
|
||||
npcsOverlayStore.clear();
|
||||
sceneDarknessStore.resetSession();
|
||||
sceneMarkerStore.resetSession();
|
||||
sceneTrapsStore.resetSession();
|
||||
sceneViewStore.reset();
|
||||
sceneTokensSessionStore.reset();
|
||||
@@ -700,6 +720,7 @@ async function main() {
|
||||
emitMaterialsOverlayState();
|
||||
emitNpcsOverlayState();
|
||||
emitSceneDarknessState();
|
||||
emitSceneMarkerState();
|
||||
emitSceneTrapsState();
|
||||
emitSceneViewState();
|
||||
emitSceneTokensSessionState();
|
||||
@@ -727,12 +748,14 @@ async function main() {
|
||||
const project = projectStore.getOpenProject();
|
||||
if (project) {
|
||||
syncSceneDarknessForProject(project);
|
||||
syncSceneMarkerForProject(project);
|
||||
syncSceneTrapsForProject(project);
|
||||
}
|
||||
emitEffectsState();
|
||||
emitMaterialsOverlayState();
|
||||
emitNpcsOverlayState();
|
||||
emitSceneDarknessState();
|
||||
emitSceneMarkerState();
|
||||
emitSceneTrapsState();
|
||||
emitSceneViewState();
|
||||
emitSceneTokensSessionState();
|
||||
@@ -755,12 +778,14 @@ async function main() {
|
||||
const project = projectStore.getOpenProject();
|
||||
if (project) {
|
||||
syncSceneDarknessForProject(project);
|
||||
syncSceneMarkerForProject(project);
|
||||
syncSceneTrapsForProject(project);
|
||||
}
|
||||
emitEffectsState();
|
||||
emitMaterialsOverlayState();
|
||||
emitNpcsOverlayState();
|
||||
emitSceneDarknessState();
|
||||
emitSceneMarkerState();
|
||||
emitSceneTrapsState();
|
||||
emitSceneViewState();
|
||||
emitSceneTokensSessionState();
|
||||
@@ -1427,6 +1452,15 @@ async function main() {
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
registerHandler(ipcChannels.sceneMarker.getState, () => {
|
||||
return { state: sceneMarkerStore.getState() };
|
||||
});
|
||||
registerHandler(ipcChannels.sceneMarker.dispatch, ({ event }) => {
|
||||
sceneMarkerStore.dispatch(event);
|
||||
emitSceneMarkerState();
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
registerHandler(ipcChannels.sceneTraps.getState, () => {
|
||||
return { state: sceneTrapsStore.getState() };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user