feat(control): история-аккордеон и форма кисти затемнения

Переименовать блок сюжетной линии в «История» и сделать его сворачиваемым. Добавить выбор круглой/квадратной формы для кистей открытия и закрытия с сохранением в штрихах и сбросом при смене инструмента или сцены без затемнения.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-09-02 10:00:10 +08:00
parent 0a9168b320
commit ea718a26df
8 changed files with 288 additions and 30 deletions
+20
View File
@@ -0,0 +1,20 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import {
normalizeSceneDarknessBrushShape,
normalizeSceneDarknessStrokeMode,
} from './sceneDarkness';
void test('normalizeSceneDarknessStrokeMode: reveal по умолчанию', () => {
assert.equal(normalizeSceneDarknessStrokeMode(undefined), 'reveal');
assert.equal(normalizeSceneDarknessStrokeMode('reveal'), 'reveal');
assert.equal(normalizeSceneDarknessStrokeMode('cover'), 'cover');
});
void test('normalizeSceneDarknessBrushShape: circle по умолчанию', () => {
assert.equal(normalizeSceneDarknessBrushShape(undefined), 'circle');
assert.equal(normalizeSceneDarknessBrushShape('circle'), 'circle');
assert.equal(normalizeSceneDarknessBrushShape('square'), 'square');
assert.equal(normalizeSceneDarknessBrushShape('triangle'), 'circle');
});
+9
View File
@@ -3,6 +3,8 @@ import type { NPoint } from './effects';
/** reveal — снимает тьму (Кисть Открытия); cover — возвращает тьму (Кисть Закрытия). */
export type SceneDarknessStrokeMode = 'reveal' | 'cover';
export type SceneDarknessBrushShape = 'circle' | 'square';
export type SceneDarknessRevealStroke = {
id: string;
seed: number;
@@ -11,12 +13,15 @@ export type SceneDarknessRevealStroke = {
radiusN: number;
/** По умолчанию reveal (старые штрихи без поля). */
mode?: SceneDarknessStrokeMode;
/** По умолчанию circle (старые штрихи без поля). */
shape?: SceneDarknessBrushShape;
};
export type SceneDarknessDraft = {
points: NPoint[];
radiusN: number;
mode?: SceneDarknessStrokeMode;
shape?: SceneDarknessBrushShape;
};
export type SceneDarknessState = {
@@ -35,3 +40,7 @@ export type SceneDarknessEvent =
export function normalizeSceneDarknessStrokeMode(raw: unknown): SceneDarknessStrokeMode {
return raw === 'cover' ? 'cover' : 'reveal';
}
export function normalizeSceneDarknessBrushShape(raw: unknown): SceneDarknessBrushShape {
return raw === 'square' ? 'square' : 'circle';
}