【问题标题】:How do I parent new, user-created buttons inside the Graph Editor window?如何在图形编辑器窗口中设置新的、用户创建的按钮?
【发布时间】:2015-11-25 20:40:58
【问题描述】:

我想在 Maya 图形编辑器中添加一些新按钮 - 特别是在窗口左侧的所有属性的通道列表顶部。但是,我宁愿不要乱用图形编辑器本身的 Maya 启动脚本。有没有办法使用单独的脚本在每个新的图表编辑器窗口中“父”我想要的新按钮?

理想情况下,这可能都是 Python。

【问题讨论】:

    标签: python window maya mel


    【解决方案1】:

    TL;DR;

    if cmds.window("GE_ui_window", exists=True): #If the window exists
        cmds.deleteUI("GE_ui_window") #Delete it
    cmds.window("GE_ui_window", title="My custom Graph Editor") #Create your custom win
    
    cmds.frameLayout("GE_ui_frameLayout", p="GE_ui_window", lv=False, bv=False ) 
    
    if cmds.scriptedPanel("GE_ui_scriptedPanel", exists=True): #If the scriptel panel already exists
        cmds.deleteUI("GE_ui_scriptedPanel") #Delete it
    cmds.scriptedPanel("GE_ui_scriptedPanel", unParent=True, type="graphEditor")
    cmds.scriptedPanel( "GE_ui_scriptedPanel", e=True, parent="GE_ui_window|GE_ui_frameLayout") #parent the scripted panel to your frame layout
    
    cmds.showWindow("GE_ui_window")
    
    channelLayout = cmds.formLayout("GE_ui_scriptedPanelOutlineEdForm", query=True, ca=True)[0] #Get the channel box's layout
    filterLayout = cmds.formLayout("GE_ui_scriptedPanelOutlineEdForm", query=True, ca=True)[1] #Get the filter's layout
    
    myRowLayout=cmds.rowLayout(numberOfColumns=3, p="GE_ui_scriptedPanelOutlineEdForm") #Create a row layout 
    cmds.button(label="Café", h=100, p=myRowLayout) #Add some buttons
    cmds.button(label="Clope", p=myRowLayout)
    cmds.button(label="Caca", p=myRowLayout)
    
    #This will reorder the content of the left formLayout
    cmds.formLayout("GE_ui_scriptedPanelOutlineEdForm", edit=True, af=[ \
                (channelLayout, "bottom", 0), \
                (channelLayout, "right", 0),  \
                (filterLayout, "top", 0),  \
                (myRowLayout, "left", 0),  \
                (myRowLayout, "right", 0)],  \
                ac=[(myRowLayout, "top", 0, filterLayout), \
                (channelLayout, "top", 0, myRowLayout)])
    

    在编辑 Maya 的 UI 时,有两件非常有用的事情需要了解。

    首先是脚本编辑器中的History -> Echo all commands 复选框。这会打印出很多垃圾,里面包含有用的信息。

    第二件事是whatIs 命令(Doc)。

    此命令接受一个字符串类型参数并返回一个字符串 指示参数是否是内置的“命令”、“梅尔 过程”、“脚本”或变量。如果是变量,则类型 也给出了变量的值。如果参数是 Mel 过程或 脚本文件,包含脚本或过程的文件的路径 包含在返回值中。

    此组合将允许您跟踪图表编辑器的创建方式和位置。现在让我们开始吧。

    1:打开图形编辑器Window -> Animation Editors -> Graph Editor

    GraphEditor;
    tearOffPanel "Graph Editor" "graphEditor" true;
    // Result: graphEditor1Window // 
    

    GraphEditor; 是一个运行时命令,它在调用时执行tearOffPanel "Graph Editor" "graphEditor" true;。这就是它出现在脚本编辑器中的原因。

    2:运行whatIs "tearOffPanel";(梅尔)

    // Result: Mel procedure found in: C:/Program Files/Autodesk/Maya2014/scripts/startup/tearOffPanel.mel // 
    

    通过对该文件的一些调查,您可以推断您可以使用scriptedPanel 命令创建一个全新的图表编辑器。

    3:创建您自己的图表面板

    scriptedPanel doc 向您展示了如何创建脚本面板并将其包含在窗口中。 您现在可以使用以下方法创建自定义图形编辑器:

    if cmds.window("GE_ui_window", exists=True):
        cmds.deleteUI("GE_ui_window")
    cmds.window("GE_ui_window", title="My custom Graph Editor")
    
    cmds.frameLayout("GE_ui_frameLayout", p="GE_ui_window", lv=False, bv=False )
    
    if cmds.scriptedPanel("GE_ui_scriptedPanel", exists=True):
        cmds.deleteUI("GE_ui_scriptedPanel")
    cmds.scriptedPanel("GE_ui_scriptedPanel", unParent=True, type="graphEditor", label='Sample')
    cmds.scriptedPanel( "GE_ui_scriptedPanel", e=True, parent="GE_ui_window|GE_ui_frameLayout")
    
    cmds.showWindow("GE_ui_window")
    

    4:尝试了解图表编辑器是如何构建的

    此脚本将打印出图表编辑器的小部件层次结构(首先创建您的自定义图表编辑器):

    nbIteration = 0
    def getChildren(uiItem, nbIteration):
        for childItem in cmds.layout(uiItem, query=True, childArray=True):
            try:
                print "|___"*nbIteration + childItem
                getChildren(uiItem + "|" + childItem, nbIteration+1)
            except:
                pass
    getChildren("GE_ui_window|GE_ui_frameLayout|GE_ui_scriptedPanel", nbIteration)
    

    另外,您可以查看C:\Program Files\Autodesk\Maya2014\scripts\others\graphEditorPanel.mel@939: global proc addGraphEditor (string $whichPanel)

    您现在可以意识到,很多小部件没有任何名称,只有 Maya 给出的默认名称。因此,我们不能使用完整路径添加小部件并将它们作为父级,因为每次创建新的图表编辑器时,此路径都会更改。

    我们将尝试依赖的项目是GE_ui_scriptedPanelOutlineEdForm,它是一个formLayout,其中包含另一个formLayout 和一个paneLayout

    |___|___GE_ui_scriptedPanelOutlineEdForm 
    |___|___|___paneLayout123 #layout containing the two channel boxes
    |___|___|___|___GE_ui_scriptedPanelOutlineEd
    |___|___|___|___GE_ui_scriptedPanelOutlineEdSlave
    |___|___|___formLayout276 #Layout containing the "filter part"
    |___|___|___|___textField63 #It's text
    |___|___|___|___iconTextButton102
    

    5:创建按钮并对GE_ui_scriptedPanelOutlineEdForm的内容重新排序

    channelLayout = cmds.formLayout("GE_ui_scriptedPanelOutlineEdForm", query=True, ca=True)[0] #Get the channel box's layout
    filterLayout = cmds.formLayout("GE_ui_scriptedPanelOutlineEdForm", query=True, ca=True)[1] #Get the filter's layout
    
    myRowLayout=cmds.rowLayout(numberOfColumns=3, p="GE_ui_scriptedPanelOutlineEdForm") #Create a row layout 
    cmds.button(label="Café", h=100, p=myRowLayout) #Add some buttons
    cmds.button(label="Clope", p=myRowLayout)
    cmds.button(label="Caca", p=myRowLayout)
    
    #This will reorder the content of the left formLayout
    cmds.formLayout("GE_ui_scriptedPanelOutlineEdForm", edit=True, af=[ \
                (channelLayout, "bottom", 0), \
                (channelLayout, "right", 0),  \
                (filterLayout, "top", 0),  \
                (myRowLayout, "left", 0),  \
                (myRowLayout, "right", 0)],  \
                ac=[(myRowLayout, "top", 0, filterLayout), \
                (channelLayout, "top", 0, myRowLayout)])
    

    【讨论】:

    • 很好,我不知道 scriptedPanel
    • 正是我想要的,谢谢!很棒的演练。
    【解决方案2】:

    为此,您可能必须使用 PySide/PyQt。找到图形编辑器的指针,找出元素的布局方式。

    这是一个关于更改 Maya 菜单样式表的示例:

    from maya.OpenMayaUI import MQtUtil as omui
    import sip
    from PyQt4 import QtGui
    
    def changeMayaMenuColors(fontStyle='italic', fontWeight='bold', fontColor='cyan'):
        # Get the widget
        widgetStr = mel.eval( 'string $tempString = $gMainCreateMenu' )
        ptr = omui.findControl( widgetStr )
        widget = sip.wrapinstance(long(ptr), QtGui.QWidget)
        widget.setStyleSheet('font-style:%s;'%fontStyle +'font-weight:%s;'%fontWeight + 'color:%s;'%fontColor)
    

    还有关于 channelBox 的一些实验:

    from PySide import QtGui, QtCore
    from shiboken import wrapInstance
    from maya.OpenMayaUI import MQtUtil
    
    
    channelbox = wrapInstance(long(MQtUtil.findControl('mainChannelBox')), QtGui.QWidget)
    channelbox_children = channelbox.children()
    
    first_widget = channelbox_children[0] # EDIT
    first_widget.hide()
    #first_widget.show()
    #---------------------------------------------------------------------------------------------------------------
    mySubWdget = first_widget.children()
    
    new_button = QtGui.QPushButton()
    new_layout = QtGui.QVBoxLayout()
    first_widget.setLayout(new_layout)
    new_layout.addWidget(new_button)
    
    def print_hodor():
        print 'HODOR'
    
    new_button.clicked.connect(print_hodor)
    

    您可以对所有 Maya 小部件进行此类实验(找到指针,然后使用 wrapInstance 获取 QT 指针,然后遍历子元素以找到您可能想要的布局)

    希望对你有帮助

    【讨论】:

    • 有没有办法让它与 PySide 一起工作?我做了一个非常基本的尝试,但在first_widget.setLayoutfirst_widget.hide 上遇到了几个错误
    • first_widget = channelbox_children[1] 应该是 "first_widget = channelbox_children[0]" 请记住,您必须检查 .children() 返回的内容才能找到布局以便插入按钮。
    猜你喜欢
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多