首页 > 解决方案 > 尝试使用单独的 py 文件在 Maya 中动态填充窗口以构建模块

问题描述

所以我正在尝试在 Maya 中构建一个窗口,它的内容将被动态填充。我的文件夹结构是这样的: /scripts/modularMenu/ <-- 其中包含:

初始化.py

模块菜单.py

和 /modules/ 文件夹

在我的模块文件夹中:modList.py

mod1.py

模组2.py

mod3.py 等等等等。

在 modMenu.py 中,我告诉 Maya 绘制窗口,但还运行根据模块文件夹的内容填充它的函数,目标是创建新模块,如果标记正确,则填充在窗口中。

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 中,我有一个类别列表和一个填充窗口的函数。

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 文件中正确导入 en群众成功调用该功能。欢迎任何帮助。

标签: pythonuser-interfacemaya

解决方案


一方面,这非常简单。如果您有对 Maya 布局的字符串引用,则始终可以将 gui 元素添加到它,使用该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 部分。最好将代码组织为常规模块,然后有一个简单的脚本明确要求模块。然后,您可以确切地知道本地安装的期望。


推荐阅读