feat(effects): вода, облако яда, луч света; пульт и окна демонстрации

- Поле: вода (сплошная заливка по штриху, превью кистью), туман/огонь/дождь без изменений логики.

- Действия: облако яда (частицы, круглая текстура, звук oblako-yada.mp3, длительность как у трека), луч света и заморозка со звуками из public/.

- Пульт: инструменты воды и яда, синхрон SFX, тесты панели и ластика.

- Окно управления: дочернее от окна просмотра (Z-order).

- Типы эффектов, effectsStore prune, hit-test ластика.

Made-with: Cursor
This commit is contained in:
Ivan Fontosh
2026-04-20 11:03:57 +08:00
parent 726c89e104
commit 20c838da7d
19 changed files with 1154 additions and 111 deletions
+14 -7
View File
@@ -118,7 +118,12 @@ export function applyDockIconIfNeeded(): void {
}
}
function createWindow(kind: WindowKind): BrowserWindow {
type CreateWindowOpts = {
/** Дочернее окно (например пульт) держится над родителем (экран просмотра). */
parent?: BrowserWindow;
};
function createWindow(kind: WindowKind, opts?: CreateWindowOpts): BrowserWindow {
const icon = resolveWindowIcon();
const win = new BrowserWindow({
width: kind === 'editor' ? 1280 : kind === 'control' ? 1200 : 1280,
@@ -126,6 +131,7 @@ function createWindow(kind: WindowKind): BrowserWindow {
show: false,
backgroundColor: '#09090B',
...(icon ? { icon } : {}),
...(opts?.parent ? { parent: opts.parent } : {}),
webPreferences: {
contextIsolation: true,
sandbox: true,
@@ -175,16 +181,17 @@ export function focusEditorWindow(): void {
}
export function openMultiWindow() {
if (!windows.has('presentation')) {
let presentation = windows.get('presentation');
if (!presentation) {
const display = screen.getPrimaryDisplay();
const { x, y, width, height } = display.bounds;
const win = createWindow('presentation');
win.setBounds({ x, y, width, height });
win.setMenuBarVisibility(false);
win.maximize();
presentation = createWindow('presentation');
presentation.setBounds({ x, y, width, height });
presentation.setMenuBarVisibility(false);
presentation.maximize();
}
if (!windows.has('control')) {
createWindow('control');
createWindow('control', { parent: presentation });
}
}