尝试使用单独的 py 文件在 Maya 中动态填充 window 以构建模块
Trying to populate a window dynamically in Maya using separate py files to essentially build modules
所以我正在尝试在 Maya 中构建一个 window,它将包含动态填充的内容。我的文件夹结构是这样的:
/scripts/modularMenu/ <-- 其中包含:
init.py
modMenu.py
和一个 /modules/ 文件夹
在 modules 文件夹中我有:
modList.py
mod1.py
mod2.py
mod3.py等等等等
在 modMenu.py 中,我告诉 Maya 绘制 window,还有 运行 根据 modules 文件夹的内容填充它的函数,使用目标是创建新的 mod 规则,如果标记正确,这些规则将填充到 window.
import maya.cmds as cmds
import sys, os.path
from functools import partial
import modules.modList as mList
def modMenu():
if (cmds.window('modMenu', exists=True)):
cmds.deleteUI('modMenu')
else:
window = cmds.window( 'modMenu', title="Mod Menu v1.1", iconName='mRig', widthHeight=(400, 800))
cmds.scrollLayout(width=400, cr=True)
cmds.columnLayout(adj=True )
#This all needs to be generated Dynamically.
mList.populateWindow()
cmds.showWindow( window )
在 modList.py 中,我有一个类别列表和一个函数来填充 window。
typeList = ['Type One', 'Type Two', Type Three']
def populateWindow():
for type in typeList:
cmds.frameLayout(label = type, collapsable = True, borderStyle = 'etchedIn')
cmds.text(label = type, al = 'center', height = 15)
#Need to then go through each module and import the rest of the form here, each form will have to have a tag to determine if it
#needs to go in this Category or not. Perhaps the equivalent of...
#for each mod.py in /modules folder if their tag == type then add
cmds.setParent( '..' )
接下来我要弄清楚的是一个,如何安全地将每个单独的 mod1.py、mod2.py 等的内容导入到这个 modList.py 文件中,以及两个如何标记每个单独的 mod.py 文件,以便将其正确放置在菜单系统中。理想情况下,我想在每个 mod.py 文件中包含一个相同的函数和一个正确标记它的字符串,我可以在 modList.py 文件中调用它,但我不确定如何正确导入那些 mod 文件一起成功调用该函数。欢迎任何帮助。
1 - 您将不得不使用 exec() 或 "import mod, mod.doIt()",但是 "safely" 是什么将取决于您的检查
2 - 我不确定是否理解。您要按编号重新排序 mod 吗?
如果没有,我想你可以做一个 json 来存储订单或者存储一些元数据
一方面,这很简单。如果您有一个字符串引用,您始终可以将 gui 元素添加到 Maya 布局,使用 setParent()
命令告诉 Maya 新内容的去向。
在这种情况下,您只需将共享布局传递给一堆函数——它们来自哪里并不重要——然后让它们分别调用“setParent”来制作布局活跃并添加到它。这是一个如何使用单独的函数而不是单独的模块的示例——如果这些不同的函数具有不同的模块来源,它不会有什么不同。
def button_section(parent):
cmds.columnLayout(adj=True)
cmds.frameLayout(label='buttons')
cmds.columnLayout(adj=True)
cmds.rowLayout(nc=2, cw = (200,200))
cmds.button(label = 'red', backgroundColor=(1,0.5,0.5), width=100)
cmds.button(label = 'blue', backgroundColor =(0.5, 0.5, 1), width=100)
def text_section(parent):
cmds.separator()
cmds.text(label = 'time:')
cmds.text(label = 'It is currently ' + str(datetime.datetime.now()))
cmds.text(label = 'main layout is ' + parent)
cmds.separator()
def object_section(parent):
cmds.columnLayout(adj=True)
cmds.frameLayout(label = 'scene')
cmds.columnLayout(adj=True, rs = 12, columnAttach = ('both', 8) )
for object in cmds.ls(type='transform'):
select_the_thing = lambda b: cmds.select(object)
cmds.button(label = object, c = select_the_thing)
def create_window(*sections):
window = cmds.window(title = 'example')
main_layout = cmds.columnLayout(adj=True)
for each_section in sections:
cmds.setParent(main_layout)
each_section(main_layout)
cmds.setParent(main_layout)
cmds.columnLayout(adj=1, columnAttach = ('both', 8))
cmds.separator()
cmds.text(label = 'here is a footer')
cmds.showWindow(window)
create_window(button_section, text_section, object_section)
如果您不熟悉语法,带 * 的 create_window
函数可以接受任意数量的参数。在这种情况下,它只是采用三个单独的部分功能。但是,您可以将其编写为只获取一个函数列表。在任何情况下,逻辑都是相同的——只需 setParent
回到主布局,您就可以向布局添加新内容。
在这个例子中,我将主布局的名称传递给了每个不同的布局函数。这很有用,因此您可以执行诸如获取拥有您的布局元素的宽度之类的操作,或者递归地提高到更高级别。
总的来说,您在这里必须注意的是设计它,以便不同的部分真正相互独立。如果 A 部分中的按钮需要知道 B 部分中复选框的状态,事情会很快变得复杂。但是,这向您展示了如何在 Maya 中组合布局的基础知识。
我会非常小心地尝试根据模块文件夹的内容填充菜单——如果您删除了一个模块但不记得删除它生成的 pyc 文件,您可以以您不期望的 UI 的幻影部分结束。最好将代码组织为常规模块,然后使用一个简单的脚本来显式请求模块。然后您就可以确切地知道本地安装会发生什么。
所以我正在尝试在 Maya 中构建一个 window,它将包含动态填充的内容。我的文件夹结构是这样的: /scripts/modularMenu/ <-- 其中包含:
init.py
modMenu.py
和一个 /modules/ 文件夹
在 modules 文件夹中我有: modList.py
mod1.py
mod2.py
mod3.py等等等等
在 modMenu.py 中,我告诉 Maya 绘制 window,还有 运行 根据 modules 文件夹的内容填充它的函数,使用目标是创建新的 mod 规则,如果标记正确,这些规则将填充到 window.
import maya.cmds as cmds
import sys, os.path
from functools import partial
import modules.modList as mList
def modMenu():
if (cmds.window('modMenu', exists=True)):
cmds.deleteUI('modMenu')
else:
window = cmds.window( 'modMenu', title="Mod Menu v1.1", iconName='mRig', widthHeight=(400, 800))
cmds.scrollLayout(width=400, cr=True)
cmds.columnLayout(adj=True )
#This all needs to be generated Dynamically.
mList.populateWindow()
cmds.showWindow( window )
在 modList.py 中,我有一个类别列表和一个函数来填充 window。
typeList = ['Type One', 'Type Two', Type Three']
def populateWindow():
for type in typeList:
cmds.frameLayout(label = type, collapsable = True, borderStyle = 'etchedIn')
cmds.text(label = type, al = 'center', height = 15)
#Need to then go through each module and import the rest of the form here, each form will have to have a tag to determine if it
#needs to go in this Category or not. Perhaps the equivalent of...
#for each mod.py in /modules folder if their tag == type then add
cmds.setParent( '..' )
接下来我要弄清楚的是一个,如何安全地将每个单独的 mod1.py、mod2.py 等的内容导入到这个 modList.py 文件中,以及两个如何标记每个单独的 mod.py 文件,以便将其正确放置在菜单系统中。理想情况下,我想在每个 mod.py 文件中包含一个相同的函数和一个正确标记它的字符串,我可以在 modList.py 文件中调用它,但我不确定如何正确导入那些 mod 文件一起成功调用该函数。欢迎任何帮助。
1 - 您将不得不使用 exec() 或 "import mod, mod.doIt()",但是 "safely" 是什么将取决于您的检查
2 - 我不确定是否理解。您要按编号重新排序 mod 吗? 如果没有,我想你可以做一个 json 来存储订单或者存储一些元数据
一方面,这很简单。如果您有一个字符串引用,您始终可以将 gui 元素添加到 Maya 布局,使用 setParent()
命令告诉 Maya 新内容的去向。
在这种情况下,您只需将共享布局传递给一堆函数——它们来自哪里并不重要——然后让它们分别调用“setParent”来制作布局活跃并添加到它。这是一个如何使用单独的函数而不是单独的模块的示例——如果这些不同的函数具有不同的模块来源,它不会有什么不同。
def button_section(parent):
cmds.columnLayout(adj=True)
cmds.frameLayout(label='buttons')
cmds.columnLayout(adj=True)
cmds.rowLayout(nc=2, cw = (200,200))
cmds.button(label = 'red', backgroundColor=(1,0.5,0.5), width=100)
cmds.button(label = 'blue', backgroundColor =(0.5, 0.5, 1), width=100)
def text_section(parent):
cmds.separator()
cmds.text(label = 'time:')
cmds.text(label = 'It is currently ' + str(datetime.datetime.now()))
cmds.text(label = 'main layout is ' + parent)
cmds.separator()
def object_section(parent):
cmds.columnLayout(adj=True)
cmds.frameLayout(label = 'scene')
cmds.columnLayout(adj=True, rs = 12, columnAttach = ('both', 8) )
for object in cmds.ls(type='transform'):
select_the_thing = lambda b: cmds.select(object)
cmds.button(label = object, c = select_the_thing)
def create_window(*sections):
window = cmds.window(title = 'example')
main_layout = cmds.columnLayout(adj=True)
for each_section in sections:
cmds.setParent(main_layout)
each_section(main_layout)
cmds.setParent(main_layout)
cmds.columnLayout(adj=1, columnAttach = ('both', 8))
cmds.separator()
cmds.text(label = 'here is a footer')
cmds.showWindow(window)
create_window(button_section, text_section, object_section)
如果您不熟悉语法,带 * 的 create_window
函数可以接受任意数量的参数。在这种情况下,它只是采用三个单独的部分功能。但是,您可以将其编写为只获取一个函数列表。在任何情况下,逻辑都是相同的——只需 setParent
回到主布局,您就可以向布局添加新内容。
在这个例子中,我将主布局的名称传递给了每个不同的布局函数。这很有用,因此您可以执行诸如获取拥有您的布局元素的宽度之类的操作,或者递归地提高到更高级别。
总的来说,您在这里必须注意的是设计它,以便不同的部分真正相互独立。如果 A 部分中的按钮需要知道 B 部分中复选框的状态,事情会很快变得复杂。但是,这向您展示了如何在 Maya 中组合布局的基础知识。
我会非常小心地尝试根据模块文件夹的内容填充菜单——如果您删除了一个模块但不记得删除它生成的 pyc 文件,您可以以您不期望的 UI 的幻影部分结束。最好将代码组织为常规模块,然后使用一个简单的脚本来显式请求模块。然后您就可以确切地知道本地安装会发生什么。