Maya快速选择工具

Maya快速选择工具
该工具通过支持通配符表达式,适用于各种复杂场景,管理选择多个物体,无论是单个名称、名称模式还是范围选择,都能轻松实现,提升工作效率和用户体验。
通配符允许输入多个,每行一个,支持 * 和 ? 符号,分别代表零个或多个字符以及一个任意字符。支持范围选择,例如使用 [n-m] 语法来匹配多个物体的名称。

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# coding=utf-8
import maya.cmds as cmds
from PySide2 import QtWidgets, QtCore, QtGui

class WildcardHighlighter(QtGui.QSyntaxHighlighter):
def __init__(self, document):
super(WildcardHighlighter, self).__init__(document)

# 定义高亮格式
self.highlighting_rules = []

# 高亮规则
green_format = QtGui.QTextCharFormat()
green_format.setForeground(QtGui.QColor("green"))
self.highlighting_rules.append((r'\[.*?\]', green_format)) # 匹配 [] 中的内容

cyan_format = QtGui.QTextCharFormat()
cyan_format.setForeground(QtGui.QColor("cyan"))
self.highlighting_rules.append((r'\*', cyan_format)) # 匹配 * 字符

yellow_format = QtGui.QTextCharFormat()
yellow_format.setForeground(QtGui.QColor("yellow"))
self.highlighting_rules.append((r'\?', yellow_format)) # 匹配 ? 字符

def highlightBlock(self, text):
for pattern, text_format in self.highlighting_rules:
regex = QtCore.QRegularExpression(pattern)
match_iterator = regex.globalMatch(text)
while match_iterator.hasNext():
match = match_iterator.next()
self.setFormat(match.capturedStart(), match.capturedLength(), text_format)

class SelectMultipleObjectsWindow(QtWidgets.QWidget):
def __init__(self):
__description__ = "快速选择工具"
__version__ = " For CGRun_v0.3"
__author__ = "Meng for CGRun_szhg"

super(SelectMultipleObjectsWindow, self).__init__()
self.setWindowTitle(u"快速选择工具" + __version__)
self.resize(650, 100) # 增加高度以容纳分隔器和多行输入框

# 设置窗口始终在最上层
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)

# 创建主布局
main_layout = QtWidgets.QVBoxLayout(self)

# 创建输入布局
input_layout = QtWidgets.QHBoxLayout()

# 创建多行文本输入框以输入通配符
self.text_edit = QtWidgets.QTextEdit(self) # 使用 QTextEdit 替换 QLineEdit
self.text_edit.setPlaceholderText("输入多个通配符,每行一个,例如:\n*Light*\n*pPlane?*\n*Sphere[3-4]*")
self.text_edit.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
input_layout.addWidget(self.text_edit)

# 初始化高亮
self.highlighter = WildcardHighlighter(self.text_edit.document())

# 创建按钮的垂直布局
button_layout = QtWidgets.QVBoxLayout()

# 创建选择按钮
self.select_button = QtWidgets.QPushButton("选择", self)
self.select_button.clicked.connect(self.select_objects)
button_layout.addWidget(self.select_button)

# 创建加选按钮
self.add_button = QtWidgets.QPushButton("加选", self)
self.add_button.clicked.connect(self.add_objects)
button_layout.addWidget(self.add_button)

# 创建减选按钮
self.remove_button = QtWidgets.QPushButton("减选", self)
self.remove_button.clicked.connect(self.remove_objects)
button_layout.addWidget(self.remove_button)

# 将按钮布局添加到输入布局中
input_layout.addLayout(button_layout)

# 创建分隔器
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)

# 创建一个容器用于输入布局
input_widget = QtWidgets.QWidget()
input_widget.setLayout(input_layout)
self.splitter.addWidget(input_widget)

# 创建说明文本框
self.instructions_text = QtWidgets.QTextEdit(self)
self.instructions_text.setPlainText(
"通配符表达式说明案例:\n"
" *表示零个或多个字符,而?表示一个任意字符。\n"
" *Light*,*Light??*,*Mesh?Shape*,*Plane2*_*01\n"
" 支持范围选择,例如:*Sphere[3-4]*"
)
self.instructions_text.setReadOnly(True) # 设置为只读
self.instructions_text.setMinimumHeight(20) # 设置说明文本框的最小高度
self.splitter.addWidget(self.instructions_text) # 将说明文本框添加到分隔器中

# 设置分隔器的初始比例,使其位于底部
self.splitter.setSizes([100, 0]) # 设置顶部部分为100,底部为70,确保说明文本框在底部可见

# 将分隔器添加到主布局
main_layout.addWidget(self.splitter)

# 设置主布局
self.setLayout(main_layout)

def process_wildcards(self, wildcard_input):
""" 处理通配符,返回符合条件的对象列表 """
all_matched_objects = []
wildcards = wildcard_input.splitlines() # 用换行符分隔输入的通配符

for wildcard in wildcards:
# 正则表达式匹配 [n-m] 格式
import re
matches = re.findall(r'\[([0-9]+)-([0-9]+)\]', wildcard)
if matches:
for match in matches:
start, end = int(match[0]), int(match[1])
# 生成通配符列表
for i in range(start, end + 1):
new_wildcard = wildcard.replace(f'[{start}-{end}]', str(i))
matched_objects = cmds.ls(new_wildcard.strip()) # 查找匹配的对象
all_matched_objects.extend(matched_objects)
else:
matched_objects = cmds.ls(wildcard.strip()) # 查找匹配的对象
all_matched_objects.extend(matched_objects)

return all_matched_objects

def select_objects(self):
wildcard_input = self.text_edit.toPlainText() # 从 QTextEdit 获取文本
all_matched_objects = self.process_wildcards(wildcard_input)

if all_matched_objects:
cmds.select(all_matched_objects) # 选择所有匹配的对象
print("选择的对象:", all_matched_objects)
else:
print("没有找到匹配的对象。")

def add_objects(self):
wildcard_input = self.text_edit.toPlainText() # 从 QTextEdit 获取文本
all_matched_objects = self.process_wildcards(wildcard_input)

if all_matched_objects:
current_selection = cmds.ls(selection=True) # 获取当前选中的对象
cmds.select(current_selection + all_matched_objects, replace=False) # 加选新的对象
print("加选的对象:", all_matched_objects)
else:
print("没有找到匹配的对象。")

def remove_objects(self):
wildcard_input = self.text_edit.toPlainText() # 从 QTextEdit 获取文本
all_matched_objects = self.process_wildcards(wildcard_input)

if all_matched_objects:
current_selection = cmds.ls(selection=True) # 获取当前选中的对象
new_selection = [obj for obj in current_selection if obj not in all_matched_objects] # 更新选择
cmds.select(new_selection) # 更新选择列表
print("减选的对象:", all_matched_objects)
else:
print("没有找到匹配的对象。")

# 创建窗口实例并显示
instance = SelectMultipleObjectsWindow()
def main():
instance.show()

main()