feat(control): 3D-кубики в отдельном окне
Бросок синхронизирован на пульте и презентации; d100 как десятки; оверлей скрывается только кнопкой «Убрать». Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -37,6 +37,7 @@ import { MaterialsOverlayStore } from './materials/materialsOverlayStore';
|
||||
import { NpcsOverlayStore } from './npcs/npcsOverlayStore';
|
||||
import { TimerSessionStore } from './sessionTimer/timerSessionStore';
|
||||
import { InitiativeSessionStore } from './initiative/initiativeSessionStore';
|
||||
import { DiceRollSessionStore } from './diceRoll/diceRollSessionStore';
|
||||
import { ZipProjectStore } from './project/zipStore';
|
||||
import { SceneViewStore } from './sceneView/sceneViewStore';
|
||||
import { registerDndAssetProtocol } from './protocol/dndAssetProtocol';
|
||||
@@ -72,6 +73,7 @@ import {
|
||||
openPlaylistsWindow,
|
||||
openTimerWindow,
|
||||
openInitiativeWindow,
|
||||
openDiceWindow,
|
||||
openMultiWindow,
|
||||
openNpcsEditorWindow,
|
||||
openSceneEditorWindow,
|
||||
@@ -82,6 +84,7 @@ import {
|
||||
closePlaylistsWindow,
|
||||
closeTimerWindow,
|
||||
closeInitiativeWindow,
|
||||
closeDiceWindow,
|
||||
closeNpcsEditorWindow,
|
||||
closeSceneEditorWindow,
|
||||
closeTokenPathEditorWindow,
|
||||
@@ -187,6 +190,7 @@ const materialsOverlayStore = new MaterialsOverlayStore();
|
||||
const npcsOverlayStore = new NpcsOverlayStore();
|
||||
const timerSessionStore = new TimerSessionStore();
|
||||
const initiativeSessionStore = new InitiativeSessionStore();
|
||||
const diceRollSessionStore = new DiceRollSessionStore();
|
||||
const sceneTokensSessionStore = new SceneTokensSessionStore();
|
||||
const tokenPathSessionStore = new TokenPathSessionStore();
|
||||
const sceneNpcTokensSessionStore = new SceneNpcTokensSessionStore();
|
||||
@@ -300,6 +304,18 @@ function emitInitiativeState(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function emitDiceRollState(): void {
|
||||
const state = diceRollSessionStore.getState();
|
||||
for (const win of BrowserWindow.getAllWindows()) {
|
||||
if (win.isDestroyed() || win.webContents.isDestroyed()) continue;
|
||||
try {
|
||||
win.webContents.send(ipcChannels.diceRoll.stateChanged, { state });
|
||||
} catch {
|
||||
/* teardown */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function syncInitiativePresenceFromSession(): void {
|
||||
const project = projectStore.getOpenProject();
|
||||
const sceneId = project?.currentSceneId ?? null;
|
||||
@@ -637,6 +653,7 @@ async function main() {
|
||||
tokenGridSnapSessionStore.reset();
|
||||
timerSessionStore.clear();
|
||||
initiativeSessionStore.clear();
|
||||
diceRollSessionStore.clear();
|
||||
if (USERS_BRANCH_FEATURES_ENABLED) {
|
||||
const playerIds = Array.isArray(req?.playerIds) ? req.playerIds.map(String).filter(Boolean) : [];
|
||||
if (playerIds.length > 0) {
|
||||
@@ -665,15 +682,18 @@ async function main() {
|
||||
emitSessionTimerState();
|
||||
syncInitiativePresenceFromSession();
|
||||
emitInitiativeState();
|
||||
emitDiceRollState();
|
||||
return { ok: true };
|
||||
});
|
||||
registerHandler(ipcChannels.windows.closeMultiWindow, () => {
|
||||
closeMultiWindow();
|
||||
timerSessionStore.clear();
|
||||
initiativeSessionStore.clear();
|
||||
diceRollSessionStore.clear();
|
||||
tokenGridSnapSessionStore.reset();
|
||||
emitSessionTimerState();
|
||||
emitInitiativeState();
|
||||
emitDiceRollState();
|
||||
emitTokenGridSnapState();
|
||||
return { ok: true };
|
||||
});
|
||||
@@ -755,6 +775,14 @@ async function main() {
|
||||
emitInitiativeState();
|
||||
return { ok: true };
|
||||
});
|
||||
registerHandler(ipcChannels.windows.openDice, () => {
|
||||
openDiceWindow();
|
||||
return { ok: true };
|
||||
});
|
||||
registerHandler(ipcChannels.windows.closeDice, () => {
|
||||
closeDiceWindow();
|
||||
return { ok: true };
|
||||
});
|
||||
registerHandler(ipcChannels.windows.openNpcsEditor, () => {
|
||||
openNpcsEditorWindow();
|
||||
return { ok: true };
|
||||
@@ -827,6 +855,14 @@ async function main() {
|
||||
emitInitiativeState();
|
||||
return { state: initiativeSessionStore.getState() };
|
||||
});
|
||||
registerHandler(ipcChannels.diceRoll.getState, () => {
|
||||
return { state: diceRollSessionStore.getState() };
|
||||
});
|
||||
registerHandler(ipcChannels.diceRoll.dispatch, ({ event }) => {
|
||||
diceRollSessionStore.dispatch(event);
|
||||
emitDiceRollState();
|
||||
return { state: diceRollSessionStore.getState() };
|
||||
});
|
||||
|
||||
registerHandler(ipcChannels.project.list, async () => {
|
||||
const projects = await projectStore.listProjects();
|
||||
@@ -870,6 +906,7 @@ async function main() {
|
||||
npcsOverlayStore.clear();
|
||||
timerSessionStore.clear();
|
||||
initiativeSessionStore.clear();
|
||||
diceRollSessionStore.clear();
|
||||
sceneDarknessStore.resetSession();
|
||||
sceneMarkerStore.resetSession();
|
||||
sceneTrapsStore.resetSession();
|
||||
@@ -884,6 +921,7 @@ async function main() {
|
||||
emitNpcsOverlayState();
|
||||
emitSessionTimerState();
|
||||
emitInitiativeState();
|
||||
emitDiceRollState();
|
||||
emitSceneDarknessState();
|
||||
emitSceneMarkerState();
|
||||
emitSceneTrapsState();
|
||||
|
||||
Reference in New Issue
Block a user