Skip to content

Commit b853f8d

Browse files
committed
feat: 增加ber和der快捷键
1 parent df49865 commit b853f8d

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

app/src/core/service/controlService/shortcutKeysEngine/shortcutKeysRegister.tsx

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,5 +990,130 @@ export class KeyBindsRegistrar {
990990
Settings.isStealthModeEnabled = !Settings.isStealthModeEnabled;
991991
toast(Settings.isStealthModeEnabled ? "已开启潜行模式" : "已关闭潜行模式");
992992
});
993+
994+
// 去除选中文本节点开头的一个字符,并将移除的字符创建为新的文本节点放在左侧 (ber 拟声词,类似"剥"或"掰"的动作)
995+
await this.project.keyBinds.create("removeFirstCharFromSelectedTextNodes", "b e r", () => {
996+
const selectedTextNodes = this.project.stageManager
997+
.getSelectedEntities()
998+
.filter((node) => node instanceof TextNode);
999+
if (selectedTextNodes.length === 0) {
1000+
return;
1001+
}
1002+
1003+
// 记录操作历史
1004+
this.project.historyManager.recordStep();
1005+
1006+
for (const node of selectedTextNodes) {
1007+
if (node.text.length > 0) {
1008+
// 获取要移除的字符
1009+
const removedChar = node.text.charAt(0);
1010+
1011+
// 更新原节点文本
1012+
node.rename(node.text.substring(1));
1013+
1014+
// 创建新的单字符节点
1015+
const rect = node.collisionBox.getRectangle();
1016+
1017+
// 创建新节点(先创建但不立即添加到舞台,以便获取其实际宽度)
1018+
const newNode = new TextNode(this.project, {
1019+
text: removedChar,
1020+
collisionBox: new CollisionBox([new Rectangle(new Vector(0, 0), new Vector(0, 0))]),
1021+
color: node.color.clone(),
1022+
});
1023+
1024+
// 计算新节点的实际宽度
1025+
const newNodeWidth = newNode.collisionBox.getRectangle().width;
1026+
1027+
// 检测左侧是否有单字符节点,如果有则将它们往左推
1028+
const textNodes = this.project.stageManager.getTextNodes();
1029+
const leftNodes = textNodes.filter(
1030+
(n) =>
1031+
n !== node &&
1032+
n.text.length === 1 &&
1033+
n.rectangle.right <= rect.left &&
1034+
Math.abs(n.rectangle.center.y - rect.center.y) < rect.size.y / 2,
1035+
);
1036+
1037+
// 按x坐标从右到左排序,确保先推最靠近原节点的
1038+
leftNodes.sort((a, b) => b.rectangle.right - a.rectangle.right);
1039+
1040+
// 推动现有节点,使用新节点的实际宽度作为推动距离
1041+
leftNodes.forEach((n) => {
1042+
n.move(new Vector(-newNodeWidth, 0));
1043+
});
1044+
1045+
// 设置新节点的位置,使其右侧边缘贴住原节点的左侧边缘
1046+
newNode.moveTo(new Vector(rect.left - newNodeWidth, rect.location.y));
1047+
// 添加到舞台
1048+
this.project.stageManager.add(newNode);
1049+
1050+
// 保持原节点的选中状态
1051+
node.isSelected = true;
1052+
}
1053+
}
1054+
});
1055+
1056+
// 去除选中文本节点结尾的一个字符,并将移除的字符创建为新的文本节点放在右侧 (der 拟声词,类似"剁"或"掉"的动作)
1057+
await this.project.keyBinds.create("removeLastCharFromSelectedTextNodes", "d e r", () => {
1058+
const selectedTextNodes = this.project.stageManager
1059+
.getSelectedEntities()
1060+
.filter((node) => node instanceof TextNode);
1061+
if (selectedTextNodes.length === 0) {
1062+
return;
1063+
}
1064+
1065+
// 记录操作历史
1066+
this.project.historyManager.recordStep();
1067+
1068+
for (const node of selectedTextNodes) {
1069+
if (node.text.length > 0) {
1070+
// 获取要移除的字符
1071+
const removedChar = node.text.charAt(node.text.length - 1);
1072+
1073+
// 更新原节点文本
1074+
node.rename(node.text.substring(0, node.text.length - 1));
1075+
1076+
// 创建新的单字符节点
1077+
const rect = node.collisionBox.getRectangle();
1078+
1079+
// 创建新节点(先创建但不立即添加到舞台,以便获取其实际宽度)
1080+
const newNode = new TextNode(this.project, {
1081+
text: removedChar,
1082+
collisionBox: new CollisionBox([new Rectangle(new Vector(0, 0), new Vector(0, 0))]),
1083+
color: node.color.clone(),
1084+
});
1085+
1086+
// 计算新节点的实际宽度
1087+
const newNodeWidth = newNode.collisionBox.getRectangle().width;
1088+
1089+
// 检测右侧是否有单字符节点,如果有则将它们往右推
1090+
const textNodes = this.project.stageManager.getTextNodes();
1091+
const rightNodes = textNodes.filter(
1092+
(n) =>
1093+
n !== node &&
1094+
n.text.length === 1 &&
1095+
n.rectangle.left >= rect.right &&
1096+
Math.abs(n.rectangle.center.y - rect.center.y) < rect.size.y / 2,
1097+
);
1098+
1099+
// 按x坐标从左到右排序,确保先推最靠近原节点的
1100+
rightNodes.sort((a, b) => a.rectangle.left - b.rectangle.left);
1101+
1102+
// 推动现有节点,使用新节点的实际宽度作为推动距离
1103+
rightNodes.forEach((n) => {
1104+
n.move(new Vector(newNodeWidth, 0));
1105+
});
1106+
1107+
// 设置新节点的位置,使其左侧边缘贴住原节点的右侧边缘
1108+
newNode.moveTo(new Vector(rect.right, rect.location.y));
1109+
1110+
// 添加到舞台
1111+
this.project.stageManager.add(newNode);
1112+
1113+
// 保持原节点的选中状态
1114+
node.isSelected = true;
1115+
}
1116+
}
1117+
});
9931118
}
9941119
}

0 commit comments

Comments
 (0)