Skip to content

Commit 3fc5634

Browse files
committed
feat: 增加狙击镜反向遮罩的功能
1 parent a1b91ee commit 3fc5634

File tree

9 files changed

+101
-17
lines changed

9 files changed

+101
-17
lines changed

app/src/core/render/canvas2d/renderer.tsx

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { getTextSize } from "@/utils/font";
99
import { isFrame, isMac } from "@/utils/platform";
1010
import { Color, mixColors, Vector } from "@graphif/data-structures";
1111
import { CubicBezierCurve, Rectangle } from "@graphif/shapes";
12+
import { GlobalMaskRenderer } from "./utilsRenderer/globalMaskRenderer";
1213

1314
/**
1415
* 渲染器
@@ -87,23 +88,7 @@ export class Renderer {
8788
this.renderMainStageElements(viewRectangle);
8889

8990
// 潜行模式 - 只显示鼠标周围的一个圆形区域
90-
if (Settings.isStealthModeEnabled) {
91-
const ctx = this.project.canvas.ctx;
92-
// 设置合成模式为目标输入模式
93-
ctx.globalCompositeOperation = "destination-in";
94-
// 获取鼠标位置
95-
const mouseX = MouseLocation.x;
96-
const mouseY = MouseLocation.y;
97-
// 获取潜行模式半径
98-
const scopeRadius = Settings.stealthModeScopeRadius;
99-
// 绘制圆形区域
100-
ctx.beginPath();
101-
ctx.arc(mouseX, mouseY, scopeRadius, 0, Math.PI * 2);
102-
ctx.fillStyle = "rgba(0, 0, 0, 1)"; // 设置填充颜色为完全不透明的黑色
103-
ctx.fill();
104-
// 恢复合成模式
105-
ctx.globalCompositeOperation = "source-over";
106-
}
91+
GlobalMaskRenderer.renderCircleMask(this.project, MouseLocation, Settings.stealthModeReverseMask);
10792

10893
this.renderViewElements(viewRectangle);
10994
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Project } from "@/core/Project";
2+
import { Settings } from "@/core/service/Settings";
3+
4+
/**
5+
* 全局遮罩渲染器
6+
*/
7+
export namespace GlobalMaskRenderer {
8+
/**
9+
* 渲染鼠标位置的圆形遮罩
10+
* @param project
11+
* @param mouseLocation
12+
* @param reverse
13+
*/
14+
export function renderCircleMask(project: Project, mouseLocation: { x: number; y: number }, reverse = false) {
15+
if (Settings.isStealthModeEnabled) {
16+
const ctx = project.canvas.ctx;
17+
// 设置合成模式为目标输入模式
18+
if (reverse) {
19+
ctx.globalCompositeOperation = "destination-out";
20+
} else {
21+
ctx.globalCompositeOperation = "destination-in";
22+
}
23+
// 获取鼠标位置
24+
const mouseX = mouseLocation.x;
25+
const mouseY = mouseLocation.y;
26+
// 获取潜行模式半径
27+
const scopeRadius = Settings.stealthModeScopeRadius;
28+
// 绘制圆形区域
29+
ctx.beginPath();
30+
ctx.arc(mouseX, mouseY, scopeRadius, 0, Math.PI * 2);
31+
ctx.fillStyle = "rgba(0, 0, 0, 1)"; // 设置填充颜色为完全不透明的黑色
32+
ctx.fill();
33+
// 恢复合成模式
34+
ctx.globalCompositeOperation = "source-over";
35+
}
36+
}
37+
38+
/**
39+
* 渲染鼠标位置的正方形遮罩
40+
* @param project
41+
* @param mouseLocation
42+
* @param reverse
43+
*/
44+
export function renderSquareMask(project: Project, mouseLocation: { x: number; y: number }, reverse = false) {
45+
if (Settings.isStealthModeEnabled) {
46+
const ctx = project.canvas.ctx;
47+
// 设置合成模式为目标输入模式
48+
if (reverse) {
49+
ctx.globalCompositeOperation = "destination-out";
50+
} else {
51+
ctx.globalCompositeOperation = "destination-in";
52+
}
53+
// 获取鼠标位置
54+
const mouseX = mouseLocation.x;
55+
const mouseY = mouseLocation.y;
56+
// 获取潜行模式半径作为正方形边长
57+
const sideLength = Settings.stealthModeScopeRadius;
58+
// 计算正方形左上角坐标(以鼠标位置为中心)
59+
const squareX = mouseX - sideLength / 2;
60+
const squareY = mouseY - sideLength / 2;
61+
// 绘制正方形区域
62+
ctx.beginPath();
63+
ctx.rect(squareX, squareY, sideLength, sideLength);
64+
ctx.fillStyle = "rgba(0, 0, 0, 1)"; // 设置填充颜色为完全不透明的黑色
65+
ctx.fill();
66+
// 恢复合成模式
67+
ctx.globalCompositeOperation = "source-over";
68+
}
69+
}
70+
}

app/src/core/service/GlobalMenu.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,19 @@ export function GlobalMenu() {
974974
<CircleDot />
975975
{activeProject ? <span>开启/关闭狙击镜</span> : "请先打开工程文件才能使用此功能"}
976976
</Item>
977+
<Item
978+
disabled={!activeProject}
979+
onClick={() => {
980+
Settings.stealthModeReverseMask = !Settings.stealthModeReverseMask;
981+
}}
982+
>
983+
<CircleDot />
984+
{activeProject ? (
985+
<span>{Settings.stealthModeReverseMask ? "关闭" : "开启"}反向遮罩</span>
986+
) : (
987+
"请先打开工程文件才能使用此功能"
988+
)}
989+
</Item>
977990
<Item
978991
disabled={!activeProject}
979992
onClick={() => {

app/src/core/service/Settings.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ export const settingsSchema = z.object({
159159
historyManagerMode: z.union([z.literal("memoryEfficient"), z.literal("timeEfficient")]).default("timeEfficient"),
160160
isStealthModeEnabled: z.boolean().default(false),
161161
stealthModeScopeRadius: z.number().min(10).max(500).int().default(150),
162+
stealthModeReverseMask: z.boolean().default(false),
162163
clearHistoryWhenManualSave: z.boolean().default(true),
163164
soundPitchVariationRange: z.number().min(0).max(1200).int().default(150),
164165
});

app/src/core/service/SettingsIcons.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Bug,
88
Calculator,
99
CaseSensitive,
10+
CircleDot,
1011
Columns4,
1112
Crosshair,
1213
Database,
@@ -153,6 +154,7 @@ export const settingsIcons = {
153154
enableRightClickConnect: MousePointerClick,
154155
isStealthModeEnabled: Crosshair,
155156
stealthModeScopeRadius: ScanEye,
157+
stealthModeReverseMask: CircleDot,
156158
clearHistoryWhenManualSave: Undo,
157159
historyManagerMode: Undo,
158160
soundPitchVariationRange: ListMusic,

app/src/locales/en.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,10 @@ settings:
498498
title: Stealth Mode Scope Radius
499499
description: |
500500
The radius of the stealth mode scope.
501+
stealthModeReverseMask:
502+
title: Reverse Mask
503+
description: |
504+
When enabled, the center area of the scope will be masked, only showing the surrounding area.
501505
502506
# Sounds
503507
cuttingLineStartSoundFile:

app/src/locales/zh_CN.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,10 @@ settings:
734734
title: 潜行模式范围半径
735735
description: |
736736
狙击镜的半径
737+
stealthModeReverseMask:
738+
title: 反向遮罩
739+
description: |
740+
开启后,狙击镜中心区域会被遮罩,只显示周围区域
737741
soundPitchVariationRange:
738742
title: 音效音调随机变化范围
739743
description: 控制音效播放时音调随机变化的程度。范围:0-1200音分(1200音分=1个八度,100音分=1个半音)。值越大,音调变化越明显。

app/src/locales/zh_TW.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ settings:
551551
title: 潜行模式范围半径
552552
description: |
553553
狙击镜的半径
554+
stealthModeReverseMask:
555+
title: 反向遮罩
556+
description: |
557+
開啟後,狙擊鏡中心區域會被遮罩,只顯示周圍區域
554558
soundPitchVariationRange:
555559
title: 音效音調随机變化範圍
556560
description: 控制音效播放時音調隨機變化的程度。範圍:0-1200音分(1200音分=1個八度,100音分=1個半音)。值越大,音調變化越明顯。

app/src/sub/SettingsWindow/settings.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ const categories = {
212212
"showBackgroundCartesian",
213213
"isStealthModeEnabled",
214214
"stealthModeScopeRadius",
215+
"stealthModeReverseMask",
215216
],
216217
node: ["enableTagTextNodesBigDisplay", "showTextNodeBorder"],
217218
edge: ["lineStyle"],

0 commit comments

Comments
 (0)