Maya 菜单中的多路径遍历和显示文件类型 Python
Multiple Paths Traversed and Displayed Filed type in Maya Menu with Python
我是新来的所以请记住这一点,我希望我的问题被清楚地问到,以便你们能帮助我。我正在尝试更改 Brent Tylers Dropbox 脚本,以便我能够在 Python 下列出 Python,在 Mel 下列出 Mel 等等(最终还有插件和其他文件,但现在不是)
好的,我的目录是这样的:
1.
sf=C:/users/scripts/ a.py + b.mel
pf=C:/users/scripts/Python/c.py
mf=C:/users/scripts/Mel/d.mel
(这些是我的脚本将放在的文件夹)
代码:
absoluteFiles = []
relativeFiles = []
folders = []
allFiles = []
currentFile = ''
for root, dirs, files in os.walk(sf):
for x in files:
correct = root.replace('\', '/')
currentFile = (correct + '/' + x)
allFiles.append(currentFile)
if currentFile.endswith('.mel'):
relativeFiles.append(currentFile.replace((mf + '/'), ""))
if currentFile.endswith('.py'):
relativeFiles.append(currentFile.replace((pf + '/'), ""))
relativeFiles.sort()
for relativeFile in relativeFiles:
split = relativeFile.split('/')
fileName = split[-1].split('.')
i=0
while i<(len(split)):
### Create Folders ###
if i==0 and len(split) != 1:
if cmds.menu(split[i] ,ex=1) == 0:
cmds.menuItem(split[i], p=PadraigsTools, bld=1, sm=1, to=1, l=split[i])
if i > 0 and i < (len(split)-1):
if cmds.menu(split[i] ,ex=1) == 0:
cmds.menuItem(split[i], p=split[i-1], bld=1, sm=1, to=1, l=split[i])
### Create .mel Files ###
if fileName[-1] == 'mel':
if i==len(split)-1 and len(split) > 1:
scriptName = split[-1].split('.')
temp1 = 'source ' + '"' + sf + '/' + relativeFile + '"; ' + scriptName[0]
command = '''mel.eval(''' + "'" + temp1 + '''')'''
cmds.menuItem(split[i], p=split[i-1], c=command, l=split[i])
if i==len(split)-1 and len(split) == 1:
scriptName = split[-1].split('.')
temp1 = 'source ' + '"' + sf + '/' + relativeFile + '"; ' + scriptName[0]
command = '''mel.eval(''' + "'" + temp1 + '''')'''
cmds.menuItem(split[i], p=Mel, c=command, l=split[i])
### Create .py Files ###
if fileName[-1] == 'py':
if i==len(split)-1 and len(split) > 1:
command = 'import ' + fileName[0] + '\n' + fileName[0] + '.' + fileName[0]+ '()'
cmds.menuItem(split[i], p=split[i-1], c=command, l=split[i])
if i==len(split)-1 and len(split) == 1:
command = 'import ' + fileName[0] + '\n' + fileName[0] + '.' + fileName[0]+ '()'
cmds.menuItem(split[i], p=Python, c=command, l=split[i])
i+=1
目前可以单独打印(sf,pf,mf)到相应的目录,但是不能一次全部列出来,sf下的文件根本不显示。关于创建的文件夹,它最终很奇怪。有时我会得到一个重复的文件夹作为子菜单,如果我使用 sf,它会给我 C:/.
经过几天几小时的研究试图修复这个脚本,我没有找到答案,包括
from itertools import chain
paths = (mf, sf, pf)
for path, dirs, files in chain.from_iterable(os.walk(path) for path in paths):
::问题::
有没有一种方法可以让我理智地把它们放在一起,这样新文件夹将在刷新时显示其内容作为子菜单,文件将显示并允许我从相应的子菜单中执行它们。
我将不胜感激任何可能的帮助,包括否决票哈哈。请记住,我不希望您用金汤匙把答案交给我,因为我不知道什么是更正或需要什么 :)
非常感谢
-- 帕德莱格
您可以做一些事情来稍微简化事情。
首先,最好让它尽可能由数据驱动,这样如果您的需求发生变化,您就不必重新编写它。这或多或少做了你所做的,但将结果收集到一个字典中,其中键是你提供的根路径,值是相对路径的列表:
def find_files(root, extensions = ('mel', 'py')):
def clean_path(*p):
return "/".join(p).replace('\', '/')
for root, _, files in os.walk(root):
used = [f for f in files if f.split(".")[-1] in extensions]
for u in used:
yield clean_path(root, u)
def relativize(abs, roots):
low_roots = map (str.lower, roots) # all lower for comparison
for root, low_root in zip(roots,low_roots):
if abs.lower().startswith(low_root):
return root, abs[len(root):]
return ("", abs)
relative_paths = find_files('c:/users/scripts')
root_dict = {}
for item in relative_paths :
folder, file = relativize(item, ('C:/users/scripts/Python/', 'C:/users/scripts/Mel/', 'C:/users/scripts/'))
if not folder in root_dict:
root_dict[folder] = []
root_dict[folder].append(file)
所以现在你有了一个字典,里面有一堆根文件夹和相对路径列表(不在你提供的任何相对路径中的文件被键入空字符串并显示为绝对路径)。您可以以非常通用的方式制作菜单,因为它们都是相同的格式。如果你需要整个列表,你可以这样获取:
results = []
for each_root in root_dict:
for relpath in root_dict[each_root]:
results.append(each_root + relpath)
为了创建实际的菜单,您希望使用单个函数并将其绑定到每个菜单项的文件名。这是一个有点棘手的话题(更多细节here)。执行此操作的简单方法是使用 functools.partial
对象,它将命令和一堆参数捆绑到一个看起来像函数的对象中:您可以创建一个部分并将其附加到菜单项的命令所以他们都用各自的参数调用同一个函数。这是一个使用上面的变量和菜单栏的简单示例;你可以看到如何很容易地使它适应其他类型的菜单:
from functools import partial
# call this on every button selection
def test(filepath, ignore):
# maya will send "test(name, False)"; we just ignore the 'False'
print "Here's where I would reload", filepath
example = cmds.window(title = 'example')
menubar = cmds.menuBarLayout()
for name in folder_names:
menuname = name
if menuname:
menuname = menuname.split("/")[-2] # we used trailing slashes
else:
menuname = "root"
cmds.menu(label = menuname)
file_names = root_dict[name]
file_names.sort()
for fn in file_names:
mi = cmds.menuItem(label = fn, command = partial(test, fn))
cmds.setParent(menubar)
我是新来的所以请记住这一点,我希望我的问题被清楚地问到,以便你们能帮助我。我正在尝试更改 Brent Tylers Dropbox 脚本,以便我能够在 Python 下列出 Python,在 Mel 下列出 Mel 等等(最终还有插件和其他文件,但现在不是)
好的,我的目录是这样的:
1.
sf=C:/users/scripts/ a.py + b.mel
pf=C:/users/scripts/Python/c.py
mf=C:/users/scripts/Mel/d.mel
(这些是我的脚本将放在的文件夹)
代码:
absoluteFiles = []
relativeFiles = []
folders = []
allFiles = []
currentFile = ''
for root, dirs, files in os.walk(sf):
for x in files:
correct = root.replace('\', '/')
currentFile = (correct + '/' + x)
allFiles.append(currentFile)
if currentFile.endswith('.mel'):
relativeFiles.append(currentFile.replace((mf + '/'), ""))
if currentFile.endswith('.py'):
relativeFiles.append(currentFile.replace((pf + '/'), ""))
relativeFiles.sort()
for relativeFile in relativeFiles:
split = relativeFile.split('/')
fileName = split[-1].split('.')
i=0
while i<(len(split)):
### Create Folders ###
if i==0 and len(split) != 1:
if cmds.menu(split[i] ,ex=1) == 0:
cmds.menuItem(split[i], p=PadraigsTools, bld=1, sm=1, to=1, l=split[i])
if i > 0 and i < (len(split)-1):
if cmds.menu(split[i] ,ex=1) == 0:
cmds.menuItem(split[i], p=split[i-1], bld=1, sm=1, to=1, l=split[i])
### Create .mel Files ###
if fileName[-1] == 'mel':
if i==len(split)-1 and len(split) > 1:
scriptName = split[-1].split('.')
temp1 = 'source ' + '"' + sf + '/' + relativeFile + '"; ' + scriptName[0]
command = '''mel.eval(''' + "'" + temp1 + '''')'''
cmds.menuItem(split[i], p=split[i-1], c=command, l=split[i])
if i==len(split)-1 and len(split) == 1:
scriptName = split[-1].split('.')
temp1 = 'source ' + '"' + sf + '/' + relativeFile + '"; ' + scriptName[0]
command = '''mel.eval(''' + "'" + temp1 + '''')'''
cmds.menuItem(split[i], p=Mel, c=command, l=split[i])
### Create .py Files ###
if fileName[-1] == 'py':
if i==len(split)-1 and len(split) > 1:
command = 'import ' + fileName[0] + '\n' + fileName[0] + '.' + fileName[0]+ '()'
cmds.menuItem(split[i], p=split[i-1], c=command, l=split[i])
if i==len(split)-1 and len(split) == 1:
command = 'import ' + fileName[0] + '\n' + fileName[0] + '.' + fileName[0]+ '()'
cmds.menuItem(split[i], p=Python, c=command, l=split[i])
i+=1
目前可以单独打印(sf,pf,mf)到相应的目录,但是不能一次全部列出来,sf下的文件根本不显示。关于创建的文件夹,它最终很奇怪。有时我会得到一个重复的文件夹作为子菜单,如果我使用 sf,它会给我 C:/.
经过几天几小时的研究试图修复这个脚本,我没有找到答案,包括
from itertools import chain
paths = (mf, sf, pf)
for path, dirs, files in chain.from_iterable(os.walk(path) for path in paths):
::问题:: 有没有一种方法可以让我理智地把它们放在一起,这样新文件夹将在刷新时显示其内容作为子菜单,文件将显示并允许我从相应的子菜单中执行它们。
我将不胜感激任何可能的帮助,包括否决票哈哈。请记住,我不希望您用金汤匙把答案交给我,因为我不知道什么是更正或需要什么 :)
非常感谢 -- 帕德莱格
您可以做一些事情来稍微简化事情。
首先,最好让它尽可能由数据驱动,这样如果您的需求发生变化,您就不必重新编写它。这或多或少做了你所做的,但将结果收集到一个字典中,其中键是你提供的根路径,值是相对路径的列表:
def find_files(root, extensions = ('mel', 'py')):
def clean_path(*p):
return "/".join(p).replace('\', '/')
for root, _, files in os.walk(root):
used = [f for f in files if f.split(".")[-1] in extensions]
for u in used:
yield clean_path(root, u)
def relativize(abs, roots):
low_roots = map (str.lower, roots) # all lower for comparison
for root, low_root in zip(roots,low_roots):
if abs.lower().startswith(low_root):
return root, abs[len(root):]
return ("", abs)
relative_paths = find_files('c:/users/scripts')
root_dict = {}
for item in relative_paths :
folder, file = relativize(item, ('C:/users/scripts/Python/', 'C:/users/scripts/Mel/', 'C:/users/scripts/'))
if not folder in root_dict:
root_dict[folder] = []
root_dict[folder].append(file)
所以现在你有了一个字典,里面有一堆根文件夹和相对路径列表(不在你提供的任何相对路径中的文件被键入空字符串并显示为绝对路径)。您可以以非常通用的方式制作菜单,因为它们都是相同的格式。如果你需要整个列表,你可以这样获取:
results = []
for each_root in root_dict:
for relpath in root_dict[each_root]:
results.append(each_root + relpath)
为了创建实际的菜单,您希望使用单个函数并将其绑定到每个菜单项的文件名。这是一个有点棘手的话题(更多细节here)。执行此操作的简单方法是使用 functools.partial
对象,它将命令和一堆参数捆绑到一个看起来像函数的对象中:您可以创建一个部分并将其附加到菜单项的命令所以他们都用各自的参数调用同一个函数。这是一个使用上面的变量和菜单栏的简单示例;你可以看到如何很容易地使它适应其他类型的菜单:
from functools import partial
# call this on every button selection
def test(filepath, ignore):
# maya will send "test(name, False)"; we just ignore the 'False'
print "Here's where I would reload", filepath
example = cmds.window(title = 'example')
menubar = cmds.menuBarLayout()
for name in folder_names:
menuname = name
if menuname:
menuname = menuname.split("/")[-2] # we used trailing slashes
else:
menuname = "root"
cmds.menu(label = menuname)
file_names = root_dict[name]
file_names.sort()
for fn in file_names:
mi = cmds.menuItem(label = fn, command = partial(test, fn))
cmds.setParent(menubar)