feat(effects): add Closing brush as inverse of Opening brush

Allow covering revealed darkness again during darkened scene sessions.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-07-30 17:21:40 +08:00
parent a3a03eb9e3
commit 41b112159f
7 changed files with 108 additions and 19 deletions
+31 -5
View File
@@ -179,6 +179,7 @@ export function ControlApp() {
| 'explosion'
| 'freeze'
| 'exploreBrush'
| 'closeBrush'
| 'eraser';
startN?: { x: number; y: number };
points?: { x: number; y: number; tMs: number }[];
@@ -1038,10 +1039,17 @@ export function ControlApp() {
draftPaintRafRef.current = 0;
pushDraftToPixi();
const b = brushRef.current;
if (b?.tool === 'exploreBrush' && b.points) {
if (
(b?.tool === 'exploreBrush' || b?.tool === 'closeBrush') &&
b.points
) {
void sd.dispatch({
kind: 'draft.set',
draft: { points: b.points, radiusN: toolRef.current.radiusN },
draft: {
points: b.points,
radiusN: toolRef.current.radiusN,
mode: b.tool === 'closeBrush' ? 'cover' : 'reveal',
},
});
}
});
@@ -1190,7 +1198,11 @@ export function ControlApp() {
},
});
}
if (b.tool === 'exploreBrush' && b.points && b.points.length > 0) {
if (
(b.tool === 'exploreBrush' || b.tool === 'closeBrush') &&
b.points &&
b.points.length > 0
) {
await sd.dispatch({
kind: 'stroke.add',
stroke: {
@@ -1199,6 +1211,7 @@ export function ControlApp() {
createdAtMs,
points: b.points,
radiusN: tool.radiusN,
mode: b.tool === 'closeBrush' ? 'cover' : 'reveal',
},
});
}
@@ -1600,6 +1613,15 @@ export function ControlApp() {
>
<span className={styles.iconGlyph}>🔦</span>
</Button>
<Button
variant={tool.tool === 'closeBrush' ? 'primary' : 'ghost'}
iconOnly
title={t('control.closerBrush')}
ariaLabel={t('control.closerBrush')}
onClick={() => selectEffectTool('closeBrush')}
>
<span className={styles.iconGlyph}></span>
</Button>
</div>
</div>
) : null}
@@ -1798,12 +1820,13 @@ export function ControlApp() {
if (tool.tool === 'water' || tool.tool === 'rain') {
extinguishFireAlong([startPt]);
}
if (tool.tool === 'exploreBrush') {
if (tool.tool === 'exploreBrush' || tool.tool === 'closeBrush') {
void sd.dispatch({
kind: 'draft.set',
draft: {
points: [startPt],
radiusN: tool.radiusN,
mode: tool.tool === 'closeBrush' ? 'cover' : 'reveal',
},
});
}
@@ -1882,7 +1905,10 @@ export function ControlApp() {
scenePanRef.current = null;
return;
}
if (brushRef.current?.tool === 'exploreBrush') {
if (
brushRef.current?.tool === 'exploreBrush' ||
brushRef.current?.tool === 'closeBrush'
) {
void sd.dispatch({ kind: 'draft.set', draft: null });
}
brushRef.current = null;