From 526b42d2fb8d2a6a28df5b895a4dc7c2fd15b994 Mon Sep 17 00:00:00 2001 From: hhhhhhhongheng <3020412479@qq.com> Date: Tue, 19 May 2026 21:07:21 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=BC=A0?= =?UTF-8?q?=E6=A0=87=E6=BB=9A=E8=BD=AE=E5=8F=8D=E5=90=91=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/core/service/Settings.tsx | 4 ++ .../controller/concrete/ControllerCamera.tsx | 58 ++++++++++--------- app/src/locales/en.yml | 12 ++++ app/src/locales/id.yml | 12 ++++ app/src/locales/zh_CN.yml | 12 ++++ app/src/locales/zh_TW.yml | 12 ++++ app/src/locales/zh_TWC.yml | 12 ++++ app/src/sub/SettingsWindow/settings.tsx | 4 ++ 8 files changed, 100 insertions(+), 26 deletions(-) diff --git a/app/src/core/service/Settings.tsx b/app/src/core/service/Settings.tsx index 4cca725a..2f2c67a7 100644 --- a/app/src/core/service/Settings.tsx +++ b/app/src/core/service/Settings.tsx @@ -82,15 +82,19 @@ export const settingsSchema = z.object({ mouseWheelMode: z .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) .default("zoom"), + mouseWheelModeReverse: z.boolean().default(false), mouseWheelWithShiftMode: z .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) .default("moveX"), + mouseWheelWithShiftModeReverse: z.boolean().default(false), mouseWheelWithCtrlMode: z .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) .default("none"), + mouseWheelWithCtrlModeReverse: z.boolean().default(false), mouseWheelWithAltMode: z .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) .default("none"), + mouseWheelWithAltModeReverse: z.boolean().default(false), doubleClickMiddleMouseButton: z.union([z.literal("adjustCamera"), z.literal("none")]).default("adjustCamera"), doubleClickMiddleMouseButtonOnEntity: z.union([z.literal("openUrl"), z.literal("none")]).default("openUrl"), mouseSideWheelMode: z diff --git a/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx b/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx index 78cae69e..f738d495 100644 --- a/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx +++ b/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx @@ -261,12 +261,13 @@ export class ControllerCameraClass extends ControllerClass { this.project.camera.targetLocationByScale = worldLocation; if (this.project.controller.pressingKeySet.has("shift")) { + const overrideDeltaY = Settings.mouseWheelWithShiftModeReverse ? -event.deltaY : undefined; if (Settings.mouseWheelWithShiftMode === "zoom") { - this.zoomCameraByMouseWheel(event); + this.zoomCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithShiftMode === "move") { - this.moveYCameraByMouseWheel(event); + this.moveYCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithShiftMode === "moveX") { - this.moveXCameraByMouseWheel(event); + this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithShiftMode === "none") { return; } @@ -275,32 +276,35 @@ export class ControllerCameraClass extends ControllerClass { this.project.controller.pressingKeySet.has("meta") ) { // 不要在节点上滚动 + const overrideDeltaY = Settings.mouseWheelWithCtrlModeReverse ? -event.deltaY : undefined; if (Settings.mouseWheelWithCtrlMode === "zoom") { - this.zoomCameraByMouseWheel(event); + this.zoomCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithCtrlMode === "move") { - this.moveYCameraByMouseWheel(event); + this.moveYCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithCtrlMode === "moveX") { - this.moveXCameraByMouseWheel(event); + this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithCtrlMode === "none") { return; } } else if (this.project.controller.pressingKeySet.has("alt")) { + const overrideDeltaY = Settings.mouseWheelWithAltModeReverse ? -event.deltaY : undefined; if (Settings.mouseWheelWithAltMode === "zoom") { - this.zoomCameraByMouseWheel(event); + this.zoomCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithAltMode === "move") { - this.moveYCameraByMouseWheel(event); + this.moveYCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithAltMode === "moveX") { - this.moveXCameraByMouseWheel(event); + this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithAltMode === "none") { return; } } else { + const overrideDeltaY = Settings.mouseWheelModeReverse ? -event.deltaY : undefined; if (Settings.mouseWheelMode === "zoom") { - this.zoomCameraByMouseWheel(event); + this.zoomCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelMode === "move") { - this.moveYCameraByMouseWheel(event); + this.moveYCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelMode === "moveX") { - this.moveXCameraByMouseWheel(event); + this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelMode === "none") { return; } @@ -366,44 +370,45 @@ export class ControllerCameraClass extends ControllerClass { this.project.camera.location = this.project.camera.location.add(diffLocation); } - private zoomCameraByMouseWheel(event: WheelEvent) { + private zoomCameraByMouseWheel(event: WheelEvent, overrideDeltaY?: number) { + const deltaY = overrideDeltaY ?? event.deltaY; if (isMac) { // mac电脑滚动一格滚轮会触发很多次事件。这个列表里是每个事件的deltaY // [7, 7, 7, 7, 6, 7, 7, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1] if (Settings.macMouseWheelIsSmoothed) { // 盲猜是开了平滑滚动了 - const deltaY = event.deltaY; this.project.camera.targetScale *= 1 + deltaY / 500; } else { // 如果没有开平滑滚动 - if (event.deltaY > 0) { + if (deltaY > 0) { this.project.camera.targetScale *= 0.8; this.project.effects.addEffect(MouseTipFeedbackEffect.default("shrink")); - } else if (event.deltaY < 0) { + } else if (deltaY < 0) { this.project.camera.targetScale *= 1.2; this.project.effects.addEffect(MouseTipFeedbackEffect.default("expand")); } } } else { - if (event.deltaY > 0) { + if (deltaY > 0) { this.project.camera.targetScale *= 0.8; this.project.effects.addEffect(MouseTipFeedbackEffect.default("shrink")); - } else if (event.deltaY < 0) { + } else if (deltaY < 0) { this.project.camera.targetScale *= 1.2; this.project.effects.addEffect(MouseTipFeedbackEffect.default("expand")); } } } - private moveYCameraByMouseWheel(event: WheelEvent) { + private moveYCameraByMouseWheel(event: WheelEvent, overrideDeltaY?: number) { + const deltaY = overrideDeltaY ?? event.deltaY; this.project.camera.bombMove( this.project.camera.location.add( - new Vector(0, (Settings.moveAmplitude * event.deltaY * 0.5) / this.project.camera.currentScale), + new Vector(0, (Settings.moveAmplitude * deltaY * 0.5) / this.project.camera.currentScale), ), ); - if (event.deltaY > 0) { + if (deltaY > 0) { this.project.effects.addEffect(MouseTipFeedbackEffect.default("moveDown")); - } else if (event.deltaY < 0) { + } else if (deltaY < 0) { this.project.effects.addEffect(MouseTipFeedbackEffect.default("moveUp")); } } @@ -479,15 +484,16 @@ export class ControllerCameraClass extends ControllerClass { } } - private moveXCameraByMouseWheel(event: WheelEvent) { + private moveXCameraByMouseWheel(event: WheelEvent, overrideDeltaY?: number) { + const deltaY = overrideDeltaY ?? event.deltaY; this.project.camera.bombMove( this.project.camera.location.add( - new Vector((Settings.moveAmplitude * event.deltaY * 0.5) / this.project.camera.currentScale, 0), + new Vector((Settings.moveAmplitude * deltaY * 0.5) / this.project.camera.currentScale, 0), ), ); - if (event.deltaY > 0) { + if (deltaY > 0) { this.project.effects.addEffect(MouseTipFeedbackEffect.default("moveRight")); - } else if (event.deltaY < 0) { + } else if (deltaY < 0) { this.project.effects.addEffect(MouseTipFeedbackEffect.default("moveLeft")); } } diff --git a/app/src/locales/en.yml b/app/src/locales/en.yml index 6d41ed89..7979bc2a 100644 --- a/app/src/locales/en.yml +++ b/app/src/locales/en.yml @@ -602,6 +602,9 @@ settings: move: Vertical Movement moveX: Horizontal Movement none: No operation + mouseWheelModeReverse: + title: Reverse Mouse Wheel + description: Reverses the direction of mouse wheel scrolling mouseWheelWithShiftMode: title: Mouse Wheel Mode with Shift Key options: @@ -609,6 +612,9 @@ settings: move: Vertical Movement moveX: Horizontal Movement none: No operation + mouseWheelWithShiftModeReverse: + title: Reverse Shift+Wheel + description: Reverses the direction of Shift+wheel scrolling mouseWheelWithCtrlMode: title: Mouse Wheel Mode with Ctrl Key options: @@ -744,6 +750,12 @@ settings: moveX: Horizontal Movement none: No operation title: Mouse Wheel Mode with Alt Key + mouseWheelWithAltModeReverse: + title: Reverse Alt+Wheel + description: Reverses the direction of Alt+wheel scrolling + mouseWheelWithCtrlModeReverse: + title: Reverse Ctrl+Wheel + description: Reverses the direction of Ctrl+wheel scrolling macTrackpadScaleSensitivity: title: MacBook trackpad two-finger zoom sensitivity description: The larger the value, the faster the scaling speed diff --git a/app/src/locales/id.yml b/app/src/locales/id.yml index 5372e466..fe788e50 100644 --- a/app/src/locales/id.yml +++ b/app/src/locales/id.yml @@ -799,6 +799,9 @@ settings: move: Gerakkan Vertikal moveX: Gerakkan Horizontal none: Tidak Ada Operasi + mouseWheelModeReverse: + title: Balikkan Roda Mouse + description: Membalikkan arah gulir roda mouse mouseWheelWithShiftMode: title: Mode Roda Mouse dengan Shift options: @@ -806,6 +809,9 @@ settings: move: Gerakkan Vertikal moveX: Gerakkan Horizontal none: Tidak Ada Operasi + mouseWheelWithShiftModeReverse: + title: Balikkan Shift+Roda + description: Membalikkan arah gulir Shift+roda mouseWheelWithCtrlMode: title: Mode Roda Mouse dengan Ctrl description: | @@ -815,6 +821,9 @@ settings: move: Gerakkan Vertikal moveX: Gerakkan Horizontal none: Tidak Ada Operasi + mouseWheelWithCtrlModeReverse: + title: Balikkan Ctrl+Roda + description: Membalikkan arah gulir Ctrl+roda mouseWheelWithAltMode: title: Mode Roda Mouse dengan Alt description: | @@ -826,6 +835,9 @@ settings: move: Gerakkan Vertikal moveX: Gerakkan Horizontal none: Tidak Ada Operasi + mouseWheelWithAltModeReverse: + title: Balikkan Alt+Roda + description: Membalikkan arah gulir Alt+roda rectangleSelectWhenLeft: title: Strategi Seleksi Kotak ke Kiri description: | diff --git a/app/src/locales/zh_CN.yml b/app/src/locales/zh_CN.yml index 01c3ebfa..7089af99 100644 --- a/app/src/locales/zh_CN.yml +++ b/app/src/locales/zh_CN.yml @@ -815,6 +815,9 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + mouseWheelModeReverse: + title: 鼠标滚轮反向 + description: 开启后鼠标滚轮的效果反转 mouseWheelWithShiftMode: title: 按住 Shift 时,鼠标滚轮模式 options: @@ -822,6 +825,9 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + mouseWheelWithShiftModeReverse: + title: Shift+滚轮反向 + description: 开启后 Shift+滚轮的效果反转 mouseWheelWithCtrlMode: title: 按住 Ctrl 时,鼠标滚轮模式 description: | @@ -831,6 +837,9 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + mouseWheelWithCtrlModeReverse: + title: Ctrl+滚轮反向 + description: 开启后 Ctrl+滚轮的效果反转 mouseWheelWithAltMode: title: 按住 Alt 时,鼠标滚轮模式 description: | @@ -842,6 +851,9 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + mouseWheelWithAltModeReverse: + title: Alt+滚轮反向 + description: 开启后 Alt+滚轮的效果反转 rectangleSelectWhenLeft: title: 向左框选的策略 description: | diff --git a/app/src/locales/zh_TW.yml b/app/src/locales/zh_TW.yml index 2074e27e..c19c02e6 100644 --- a/app/src/locales/zh_TW.yml +++ b/app/src/locales/zh_TW.yml @@ -815,6 +815,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + mouseWheelModeReverse: + title: 鼠標滾輪反向 + description: 開啟後鼠標滾輪的效果反轉 mouseWheelWithShiftMode: title: 按住 Shift 時,鼠標滾輪模式 options: @@ -822,6 +825,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + mouseWheelWithShiftModeReverse: + title: Shift+滾輪反向 + description: 開啟後 Shift+滾輪的效果反轉 mouseWheelWithCtrlMode: title: 按住 Ctrl 時,鼠標滾輪模式 description: | @@ -831,6 +837,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + mouseWheelWithCtrlModeReverse: + title: Ctrl+滾輪反向 + description: 開啟後 Ctrl+滾輪的效果反轉 mouseWheelWithAltMode: title: 按住 Alt 時,鼠標滾輪模式 description: | @@ -842,6 +851,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + mouseWheelWithAltModeReverse: + title: Alt+滾輪反向 + description: 開啟後 Alt+滾輪的效果反轉 rectangleSelectWhenLeft: title: 向左框選的策略 description: | diff --git a/app/src/locales/zh_TWC.yml b/app/src/locales/zh_TWC.yml index a8d23eb0..d2911f9f 100644 --- a/app/src/locales/zh_TWC.yml +++ b/app/src/locales/zh_TWC.yml @@ -821,6 +821,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 无操作 + mouseWheelModeReverse: + title: 滑鼠滾輪反向 + description: 開啟後滑鼠滾輪的效果反轉 mouseWheelWithShiftMode: title: 按住 Shift 時,滑鼠滾輪模式 options: @@ -828,6 +831,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 无操作 + mouseWheelWithShiftModeReverse: + title: Shift+滾輪反向 + description: 開啟後 Shift+滾輪的效果反轉 mouseWheelWithCtrlMode: title: 按住 Ctrl 時,滑鼠滾輪模式 description: '提示:这里的 Ctrl 是 Control @@ -838,6 +844,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 无操作 + mouseWheelWithCtrlModeReverse: + title: Ctrl+滾輪反向 + description: 開啟後 Ctrl+滾輪的效果反轉 mouseWheelWithAltMode: title: 按住 Alt 時,滑鼠滾輪模式 description: '此功能於2025年4月10日新增 @@ -850,6 +859,9 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 无操作 + mouseWheelWithAltModeReverse: + title: Alt+滾輪反向 + description: 開啟後 Alt+滾輪的效果反轉 rectangleSelectWhenLeft: title: 向左框選的策略 description: '選擇滑鼠向左框選的策略,包含完全覆蓋框選和碰撞框選 diff --git a/app/src/sub/SettingsWindow/settings.tsx b/app/src/sub/SettingsWindow/settings.tsx index 00582f34..2302e3e3 100644 --- a/app/src/sub/SettingsWindow/settings.tsx +++ b/app/src/sub/SettingsWindow/settings.tsx @@ -274,9 +274,13 @@ const categories = { "enableDragAutoAlign", "reverseTreeMoveMode", "mouseWheelMode", + "mouseWheelModeReverse", "mouseWheelWithShiftMode", + "mouseWheelWithShiftModeReverse", "mouseWheelWithCtrlMode", + "mouseWheelWithCtrlModeReverse", "mouseWheelWithAltMode", + "mouseWheelWithAltModeReverse", "doubleClickMiddleMouseButton", "doubleClickMiddleMouseButtonOnEntity", "mouseSideWheelMode", From b6ef1179e233e70272a99d43da1e88a8d261d81b Mon Sep 17 00:00:00 2001 From: hhhhhhhongheng <3020412479@qq.com> Date: Tue, 19 May 2026 23:58:10 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BC=A9?= =?UTF-8?q?=E6=94=BE=20UI=20=E6=8E=A7=E5=88=B6=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/App.tsx | 113 ++++++++++-------- app/src/core/service/Settings.tsx | 9 +- app/src/core/service/SettingsIcons.tsx | 1 + .../controller/concrete/ControllerCamera.tsx | 19 +++ .../shortcutKeysEngine/KeyBindHintEngine.tsx | 27 +++-- app/src/locales/zh_CN.yml | 8 ++ app/src/locales/zh_TW.yml | 8 ++ app/src/sub/SettingsWindow/settings.tsx | 1 + 8 files changed, 120 insertions(+), 66 deletions(-) diff --git a/app/src/App.tsx b/app/src/App.tsx index 80203736..872552c1 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -49,6 +49,7 @@ export default function App() { const [isClassroomMode, setIsClassroomMode] = useAtom(isClassroomModeAtom); const [showQuickSettingsToolbar, setShowQuickSettingsToolbar] = useState(Settings.showQuickSettingsToolbar); const [windowBackgroundAlpha, setWindowBackgroundAlpha] = useState(Settings.windowBackgroundAlpha); + const [uiScalePercent, setUiScalePercent] = useState(Settings.uiScalePercent); const contextMenuTriggerRef = useRef(null); @@ -112,6 +113,12 @@ export default function App() { setWindowBackgroundAlpha(value); }); + // 初始化 UI 缩放(只缩放 UI 组件层,不缩放 Canvas 画布) + setUiScalePercent(Settings.uiScalePercent); + const unwatchUiScale = Settings.watch("uiScalePercent", (value) => { + setUiScalePercent(value); + }); + // 恢复窗口位置大小 restoreStateCurrent(StateFlags.SIZE | StateFlags.POSITION | StateFlags.MAXIMIZED); @@ -158,6 +165,7 @@ export default function App() { // 清理全局快捷键资源 unwatchShowQuickSettingsToolbar(); unwatchWindowBackgroundAlpha(); + unwatchUiScale(); globalShortcutManager.dispose(); }; }, []); @@ -324,6 +332,9 @@ export default function App() { [closeTab], ); + const zoomStyle = uiScalePercent !== 100 ? { zoom: `${uiScalePercent / 100}` } as React.CSSProperties : undefined; + const zoomClass = "relative z-10 flex h-full w-full flex-col gap-2 pointer-events-none [&>*]:pointer-events-auto"; + return ( <> {/* 这是一个底层的 div,用于在拖拽改变窗口大小时填充背景,防止窗口出现透明闪烁 */} @@ -332,36 +343,7 @@ export default function App() { className="relative flex h-full w-full flex-col overflow-clip rounded-lg sm:gap-2 sm:p-2" onContextMenu={(e) => e.preventDefault()} > - {/* 菜单 | 标签页 | ...移动窗口区域... | 窗口控制按钮 */} -
-
- {isMac && } - -
- - {!isMac && } -
- - - - {/* content */} + {/* Canvas content - NOT zoomed */} {tabs.map((p) => (
))} - {/* 没有项目处于打开状态时,显示欢迎页面 */} - {tabs.length === 0 && ( -
- + {/* Zoomed UI layer - 只缩放主窗口的 UI 组件,不缩放 Canvas 画布 */} +
+ {/* 菜单 | 标签页 | ...移动窗口区域... | 窗口控制按钮 */} +
+
+ {isMac && } + +
+ + {!isMac && }
- )} - - {/* 右键菜单 */} - - -
- - - - {/* ======= */} - {/* */} + - {/* */} + {/* 没有项目处于打开状态时,显示欢迎页面 */} + {tabs.length === 0 && ( +
+ +
+ )} - {/* - */} + {/* 右键菜单 */} + + +
+ + + - + {/* 底部工具栏 */} + {activeTab && } - {/* 底部工具栏 */} - {activeTab && } + {/* 右侧工具栏 */} + {activeTab && showQuickSettingsToolbar && } +
- {/* 右侧工具栏 */} - {activeTab && showQuickSettingsToolbar && } + {/* NOT zoomed - 使用固定/全屏定位的组件,缩放会破坏它们的位置计算 */} + {/* 右上角关闭的触发角 */} {isWindows && ( diff --git a/app/src/core/service/Settings.tsx b/app/src/core/service/Settings.tsx index 2f2c67a7..6039969b 100644 --- a/app/src/core/service/Settings.tsx +++ b/app/src/core/service/Settings.tsx @@ -80,21 +80,22 @@ export const settingsSchema = z.object({ enableDragAutoAlign: z.boolean().default(false), reverseTreeMoveMode: z.boolean().default(false), mouseWheelMode: z - .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) + .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none"), z.literal("zoomUI")]) .default("zoom"), mouseWheelModeReverse: z.boolean().default(false), mouseWheelWithShiftMode: z - .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) + .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none"), z.literal("zoomUI")]) .default("moveX"), mouseWheelWithShiftModeReverse: z.boolean().default(false), mouseWheelWithCtrlMode: z - .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) + .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none"), z.literal("zoomUI")]) .default("none"), mouseWheelWithCtrlModeReverse: z.boolean().default(false), mouseWheelWithAltMode: z - .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none")]) + .union([z.literal("zoom"), z.literal("move"), z.literal("moveX"), z.literal("none"), z.literal("zoomUI")]) .default("none"), mouseWheelWithAltModeReverse: z.boolean().default(false), + uiScalePercent: z.number().min(25).max(200).default(100), doubleClickMiddleMouseButton: z.union([z.literal("adjustCamera"), z.literal("none")]).default("adjustCamera"), doubleClickMiddleMouseButtonOnEntity: z.union([z.literal("openUrl"), z.literal("none")]).default("openUrl"), mouseSideWheelMode: z diff --git a/app/src/core/service/SettingsIcons.tsx b/app/src/core/service/SettingsIcons.tsx index f90f00c5..8f092f27 100644 --- a/app/src/core/service/SettingsIcons.tsx +++ b/app/src/core/service/SettingsIcons.tsx @@ -107,6 +107,7 @@ export const settingsIcons = { mouseLeftMode: MouseLeft, enableDragAutoAlign: AlignStartVertical, reverseTreeMoveMode: Move, + uiScalePercent: Scaling, mouseWheelMode: LoaderPinwheel, mouseWheelWithShiftMode: LoaderPinwheel, mouseWheelWithCtrlMode: LoaderPinwheel, diff --git a/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx b/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx index f738d495..789b402d 100644 --- a/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx +++ b/app/src/core/service/controlService/controller/concrete/ControllerCamera.tsx @@ -253,6 +253,17 @@ export class ControllerCameraClass extends ControllerClass { * @param event * @returns */ + private zoomUIMethod(event: WheelEvent, overrideDeltaY?: number) { + const deltaY = overrideDeltaY ?? event.deltaY; + const step = 25; + const current = Settings.uiScalePercent; + if (deltaY > 0) { + Settings.uiScalePercent = Math.max(25, current - step); + } else if (deltaY < 0) { + Settings.uiScalePercent = Math.min(200, current + step); + } + } + private mousewheelFunction(event: WheelEvent) { // 获取触发滚轮的鼠标位置 const mouseLocation = new Vector(event.clientX, event.clientY); @@ -270,6 +281,8 @@ export class ControllerCameraClass extends ControllerClass { this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithShiftMode === "none") { return; + } else if (Settings.mouseWheelWithShiftMode === "zoomUI") { + this.zoomUIMethod(event, overrideDeltaY); } } else if ( this.project.controller.pressingKeySet.has("control") || @@ -285,6 +298,8 @@ export class ControllerCameraClass extends ControllerClass { this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithCtrlMode === "none") { return; + } else if (Settings.mouseWheelWithCtrlMode === "zoomUI") { + this.zoomUIMethod(event, overrideDeltaY); } } else if (this.project.controller.pressingKeySet.has("alt")) { const overrideDeltaY = Settings.mouseWheelWithAltModeReverse ? -event.deltaY : undefined; @@ -296,6 +311,8 @@ export class ControllerCameraClass extends ControllerClass { this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelWithAltMode === "none") { return; + } else if (Settings.mouseWheelWithAltMode === "zoomUI") { + this.zoomUIMethod(event, overrideDeltaY); } } else { const overrideDeltaY = Settings.mouseWheelModeReverse ? -event.deltaY : undefined; @@ -307,6 +324,8 @@ export class ControllerCameraClass extends ControllerClass { this.moveXCameraByMouseWheel(event, overrideDeltaY); } else if (Settings.mouseWheelMode === "none") { return; + } else if (Settings.mouseWheelMode === "zoomUI") { + this.zoomUIMethod(event, overrideDeltaY); } } diff --git a/app/src/core/service/controlService/shortcutKeysEngine/KeyBindHintEngine.tsx b/app/src/core/service/controlService/shortcutKeysEngine/KeyBindHintEngine.tsx index 42d50601..5fdcccc8 100644 --- a/app/src/core/service/controlService/shortcutKeysEngine/KeyBindHintEngine.tsx +++ b/app/src/core/service/controlService/shortcutKeysEngine/KeyBindHintEngine.tsx @@ -9,6 +9,11 @@ import { KeyBindsUI, type UIKeyBind } from "./KeyBindsUI"; import { formatKeyBindSequenceToString } from "@/utils/keyDisplay"; import i18next from "i18next"; +// 根据 UI 缩放比例计算缩放后的字号 +function scaledFontSize(base: number): number { + return base * (Settings.uiScalePercent / 100); +} + /** * 快捷键提示引擎 * 当按下修饰键时,显示匹配的快捷键提示 @@ -260,10 +265,12 @@ export class KeyBindHintEngine { const endIndex = Math.min(startIndex + this.ITEMS_PER_PAGE, this.cachedKeyBinds.length); const pageItems = this.cachedKeyBinds.slice(startIndex, endIndex); + const scale = Settings.uiScalePercent / 100; + // 计算起始位置(在左下角按键提示的上方) - const margin = 10; - const lineHeight = 28; - const startY = this.project.renderer.h - 140 - pageItems.length * lineHeight; + const margin = 10 * scale; + const lineHeight = 28 * scale; + const startY = this.project.renderer.h - 140 * scale - pageItems.length * lineHeight; // 渲染每个快捷键提示 for (let i = 0; i < pageItems.length; i++) { @@ -273,20 +280,22 @@ export class KeyBindHintEngine { // 使用复用的函数格式化修饰键组合 let currentX = margin; + const keyFontSize = scaledFontSize(16); // 渲染按键 this.project.textRenderer.renderText( item.displayKey, new Vector(currentX, y), - 16, + keyFontSize, this.project.stageStyleManager.currentStyle.effects.flash, ); - currentX += getTextSize(item.displayKey, 16).x; + currentX += getTextSize(item.displayKey, keyFontSize).x; + const titleFontSize = scaledFontSize(12); // 渲染标题 this.project.textRenderer.renderText( item.title, - new Vector(currentX + 15, y + 2), - 12, + new Vector(currentX + 15 * scale, y + 2 * scale), + titleFontSize, this.project.stageStyleManager.currentStyle.DetailsDebugText, ); } @@ -296,8 +305,8 @@ export class KeyBindHintEngine { const pageIndicator = `${actualPage + 1}/${totalPages}`; this.project.textRenderer.renderText( pageIndicator, - new Vector(margin, startY - 20), - 12, + new Vector(margin, startY - 20 * scale), + scaledFontSize(12), this.project.stageStyleManager.currentStyle.DetailsDebugText, ); } diff --git a/app/src/locales/zh_CN.yml b/app/src/locales/zh_CN.yml index 7089af99..694d2860 100644 --- a/app/src/locales/zh_CN.yml +++ b/app/src/locales/zh_CN.yml @@ -808,6 +808,10 @@ settings: cameraMoveToMouse: 将视野向鼠标位置移动 adjustWindowOpacity: 调整窗口透明度 adjustPenStrokeWidth: 调整画笔粗细 + uiScalePercent: + title: UI 缩放比例 + description: | + 缩放 UI 界面元素和字体的大小,范围 25% ~ 200%。 mouseWheelMode: title: 鼠标滚轮模式 options: @@ -815,6 +819,7 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + zoomUI: 缩放UI mouseWheelModeReverse: title: 鼠标滚轮反向 description: 开启后鼠标滚轮的效果反转 @@ -825,6 +830,7 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + zoomUI: 缩放UI mouseWheelWithShiftModeReverse: title: Shift+滚轮反向 description: 开启后 Shift+滚轮的效果反转 @@ -837,6 +843,7 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + zoomUI: 缩放UI mouseWheelWithCtrlModeReverse: title: Ctrl+滚轮反向 description: 开启后 Ctrl+滚轮的效果反转 @@ -851,6 +858,7 @@ settings: move: 纵向移动 moveX: 横向移动 none: 无操作 + zoomUI: 缩放UI mouseWheelWithAltModeReverse: title: Alt+滚轮反向 description: 开启后 Alt+滚轮的效果反转 diff --git a/app/src/locales/zh_TW.yml b/app/src/locales/zh_TW.yml index c19c02e6..28eb479b 100644 --- a/app/src/locales/zh_TW.yml +++ b/app/src/locales/zh_TW.yml @@ -808,6 +808,10 @@ settings: cameraMoveToMouse: 將視野向鼠標位置移動 adjustWindowOpacity: 調整窗口透明度 adjustPenStrokeWidth: 調整畫筆粗細 + uiScalePercent: + title: UI 縮放比例 + description: | + 縮放 UI 界面元素和字體的大小,範圍 25% ~ 200%。 mouseWheelMode: title: 鼠標滾輪模式 options: @@ -815,6 +819,7 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + zoomUI: 縮放UI mouseWheelModeReverse: title: 鼠標滾輪反向 description: 開啟後鼠標滾輪的效果反轉 @@ -825,6 +830,7 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + zoomUI: 縮放UI mouseWheelWithShiftModeReverse: title: Shift+滾輪反向 description: 開啟後 Shift+滾輪的效果反轉 @@ -837,6 +843,7 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + zoomUI: 縮放UI mouseWheelWithCtrlModeReverse: title: Ctrl+滾輪反向 description: 開啟後 Ctrl+滾輪的效果反轉 @@ -851,6 +858,7 @@ settings: move: 縱向移動 moveX: 橫向移動 none: 無操作 + zoomUI: 縮放UI mouseWheelWithAltModeReverse: title: Alt+滾輪反向 description: 開啟後 Alt+滾輪的效果反轉 diff --git a/app/src/sub/SettingsWindow/settings.tsx b/app/src/sub/SettingsWindow/settings.tsx index 2302e3e3..9db67e18 100644 --- a/app/src/sub/SettingsWindow/settings.tsx +++ b/app/src/sub/SettingsWindow/settings.tsx @@ -209,6 +209,7 @@ const categories = { "windowBackgroundAlpha", "windowBackgroundOpacityAfterOpenClickThrough", "windowBackgroundOpacityAfterCloseClickThrough", + "uiScalePercent", ], background: [ "isRenderCenterPointer",