尝试使用单独的 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 的幻影部分结束。最好将代码组织为常规模块,然后使用一个简单的脚本来显式请求模块。然后您就可以确切地知道本地安装会发生什么。