citybybay1
citybybay1

Reputation: 1

Create parent/child slider set in MAYA Attribute Editor

I am trying to create a slider setup for an Attribute Editor view. I know I have to setup a callback but have been stumpt. The goal is to have a parent slider with two children. The purpose is for pose control is when you have, ie, both arms going up for the parent and individual controls to each arm being the children. I have been able to do this if I create a UI window but have not been able to get it to work as an AE template. This is the code that works for the UI window.

class frGUI(object):
    def add_sliders(self, *_):
        # The test sliders
        self.parentval[0] = 0
        self.slider[0] = pm.floatSliderGrp(l='Up-Down', p=self.frame1111, f=True, min=-100.0, max=100.0,
                                           v=0.0, cc=lambda *_: self.update_children(0, 1, 2),
                                           dc=lambda *_: self.update_children(0, 1, 2))
        self.offsetval[1] = 0
        self.slider[1] = pm.floatSliderGrp(l='Up-Down Left', p=self.frame1111, f=True, min=-100.0, max=100.0,
                                           v=0.0, cc=lambda *_: self.update_child_offset(0, 1),
                                           dc=lambda *_: self._up_down_left())
        self.offsetval[2] = 0
        self.slider[2] = pm.floatSliderGrp(l='Up-Down Right', p=self.frame1111, f=True, min=-100.0, max=100.0,
                                           v=0.0, cc=lambda *_: self.update_child_offset(0, 2),
                                           dc=lambda *_: self._up_down_right())
    def __init__(self):
        self.parentval = {}
        self.offsetval = {}
        self.slider = {}
        if pm.window('mainwindow', exists=True):
            pm.deleteUI('mainwindow')
        self.window = pm.window('mainwindow', title='Test Rig', w=425, h=600, mxb=False, mnb=True)
        pm.scrollLayout()
        # First-level tabs
        tab1 = pm.tabLayout(w=405, h=600, imw=5, imh=5)
        # First second-level tab
        form111 = pm.formLayout()
        pm.frameLayout(w=385, lv=False)
        self.frame1111 = pm.frameLayout(lv=False, bv=True)
        pm.setParent('..')
        pm.setParent('..')
        pm.setParent('..')
        pm.tabLayout(tab1, edit=True, tabLabel=((form111, 'Test')))
        self.add_sliders(self)
        pm.showWindow(self.window)

    def _up_down(self, *_):
        self._up_down_left()
        self._up_down_right()

    def _up_down_left(self, *_):
        self.update_lShldrBend()

    def _up_down_right(self, *_):
        self.update_rShldrBend()

    def update_lShldrBend(self, *_):
        value = pm.floatSliderGrp(self.slider[1], q=True, v=True)
        pm.setAttr('lShldrBend.rotateZ', value)

    def update_rShldrBend(self, *_):
        value = pm.floatSliderGrp(self.slider[2], q=True, v=True)*(-1)
        pm.setAttr('rShldrBend.rotateZ', value)

    def update_children(self, parent, child1, child2, *_):
        child1lab = pm.floatSliderGrp(self.slider[child1], q=True, l=True)
        child2lab = pm.floatSliderGrp(self.slider[child2], q=True, l=True)
        child1par = pm.floatSliderGrp(self.slider[child1], q=True, p=True)
        child2par = pm.floatSliderGrp(self.slider[child2], q=True, p=True)
        child1min = pm.floatSliderGrp(self.slider[child1], q=True, min=True)
        child2min = pm.floatSliderGrp(self.slider[child2], q=True, min=True)
        pm.deleteUI(self.slider[child1])
        pm.deleteUI(self.slider[child2])
        self.parentval[parent] = pm.floatSliderGrp(self.slider[parent], q=True, v=True)
        child1val = self.offsetval[child1] + self.parentval[parent]
        child2val = self.offsetval[child2] + self.parentval[parent]
        self.slider[child1] = pm.floatSliderGrp(l=child1lab, p=child1par, f=True, min=child1min, max=100.0,
                                                v=child1val, cc=lambda *_: self.update_child_offset(0, 1),
                                                dc=lambda *_: self._up_down_left(1))
        self.slider[child2] = pm.floatSliderGrp(l=child2lab, p=child2par, f=True, min=child2min, max=100.0,
                                                v=child2val, cc=lambda *_: self.update_child_offset(0, 2),
                                                dc=lambda *_: self._up_down_right(2))
        if parent == 0:
            self._up_down()

    def update_child_offset(self, parent, child, *_):
        childval = pm.floatSliderGrp(self.slider[child], q=True, v=True)
        self.offsetval[child] = childval - self.parentval[parent]
        if child == 1:
            self._up_down_left()
        elif child == 2:
            self._up_down_right()

import maya.cmds as cmds
import pymel.core as pm

example = frGUI()

I'm new to MAYA coding on this level but have done a fare bit elsewhere.

Upvotes: 0

Views: 385

Answers (1)

haggi krey
haggi krey

Reputation: 1978

You can use a node template with pymel like this:

import pymel.core as pm
    
class BaseTemplate(pm.ui.AETemplate):
    
    def addControl(self, control, label=None, **kwargs):
        pm.ui.AETemplate.addControl(self, control, label=label, **kwargs)
        
    def beginLayout(self, name, collapse=True):
        pm.ui.AETemplate.beginLayout(self, name, collapse=collapse)

class AEmyownNodeTemplate(BaseTemplate):
    def __init__(self, nodeName):
        BaseTemplate.__init__(self,nodeName)
        self.thisNode = None
        self.ksrType = None
        self.node = pm.PyNode(self.nodeName)
        self.buildBody(nodeName)        
   
    def buildMyOwnTemplates(self, nodeName):
        self.thisNode = pm.PyNode(nodeName)
        if self.thisNode.type() in ['mesh']:
            self.beginLayout("MyOwnLayout" ,collapse=1)
            self.endLayout()
    
    def buildBody(self, nodeName):
        self.buildMyOwnTemplates(nodeName)

Let's say it it saved somewhere in the pythonpath as aeNodeTemplate.py then you can use it together with a callback in userSetup:

import pymel.core as pm
import aeNodeTemplate

pm.callbacks(addCallback=aeNodeTemplate.AEmyownNodeTemplate, hook='AETemplateCustomContent', owner="me")

This should work for all mesh nodes where a new layout named MyOwnLayout should appear.

Upvotes: 1

Related Questions