def initialize(): """ Initializes the node. """ # guide attributes fn_num = oMa.MFnNumericAttribute() SeamlessFkIk.thigh_len_mobj = fn_num.create("thighLen", "tl", oMa.MFnNumericData.kFloat) SeamlessFkIk.shin_len_mobj = fn_num.create("shinLen", "sl", oMa.MFnNumericData.kFloat) # message attributes fn_message = oMa.MFnMessageAttribute() SeamlessFkIk.fk_01_mobj = fn_message.create("fk01", "fk01") SeamlessFkIk.fk_02_mobj = fn_message.create("fk02", "fk02") SeamlessFkIk.fk_03_mobj = fn_message.create("fk03", "fk03") SeamlessFkIk.ik_main_mobj = fn_message.create("ikMain", "ikm") SeamlessFkIk.ik_pole_mobj = fn_message.create("ikPole", "ikp") # add attributes SeamlessFkIk.addAttribute(SeamlessFkIk.thigh_len_mobj) SeamlessFkIk.addAttribute(SeamlessFkIk.shin_len_mobj) SeamlessFkIk.addAttribute(SeamlessFkIk.fk_01_mobj) SeamlessFkIk.addAttribute(SeamlessFkIk.fk_02_mobj) SeamlessFkIk.addAttribute(SeamlessFkIk.fk_03_mobj) SeamlessFkIk.addAttribute(SeamlessFkIk.ik_main_mobj) SeamlessFkIk.addAttribute(SeamlessFkIk.ik_pole_mobj)
def createSrcMsgAttr(longName, shortName): """Create a source (a.k.a. output, or readable) message attribute.""" msgAttrFn = OpenMaya.MFnMessageAttribute() attr = msgAttrFn.create(longName, shortName) msgAttrFn.writable = False msgAttrFn.storable = False return attr
def _addOutputControls(obj, side): ''' Adds attributes to card for tracking the created controls. Used in conjunction with OutputControls. :param PyNode obj: The card to add attributes to :param str side: Either "Left", "Right" or "Center" ''' if obj.hasAttr('output' + side): return mobj = core.capi.asMObject(obj) cattr = OpenMaya.MFnCompoundAttribute() mattr = OpenMaya.MFnMessageAttribute() nattr = OpenMaya.MFnNumericAttribute() extraNodes = cattr.create('output' + side, 'out' + side[0]) cattr.array = True link = mattr.create('outputLink' + side, 'ol' + side[0]) type = nattr.create('out' + side + 'Type', 'o' + side[0] + 't', OpenMaya.MFnNumericData.kInt, 0) cattr.addChild(link) cattr.addChild(type) mobj.addAttribute(extraNodes)
def _addSeqAttr(obj): ''' Add `.sequence` attribute to a Script node to enable the custom Sequence api. Safe to run repeatedly since it only adds required attrs. ''' if not obj: return if not obj.hasAttr('sequence'): mobj = core.capi.asMObject(obj) cattr = OpenMaya.MFnCompoundAttribute() nattr = OpenMaya.MFnNumericAttribute() tattr = OpenMaya.MFnTypedAttribute() mattr = OpenMaya.MFnMessageAttribute() sequence = cattr.create("sequence", 'seq') cattr.array = True for long, short, type in _dataSequenceAttr: if type is OpenMaya.MFnStringData.kString: newAttr = tattr.create(long, short, type) elif type is OpenMaya.MFnNumericData.kInt: newAttr = nattr.create(long, short, type, 0) elif type == 'message': newAttr = mattr.create(long, short) cattr.addChild(newAttr) mobj.addAttribute(sequence) if not obj.hasAttr('animNotes'): obj.addAttr('animNotes', dt='string') obj.animNotes.set('')
def createDstMsgAttr(longName, shortName): """Create a destination (a.k.a. input, or writable) message attribute.""" msgAttrFn = OpenMaya.MFnMessageAttribute() attr = msgAttrFn.create(longName, shortName) msgAttrFn.writable = True # Since message attributes carry no data, does storable mean anything? msgAttrFn.storable = True return attr
def parseMessageAttribute(self, name, shortName, attrInfo): """ Given a JSON subsection describing a message attribute create the attribute and set all of the provided flags/members for it. name = Attribute long name shortName = Attribute short name attrInfo = JSON object containing the main attribute information """ jsonDebug('parseMessageAttribute(%s)' % name) mAttr = omAPI.MFnMessageAttribute() jsonDebug('Creating message attribute') attr = mAttr.create(name, shortName) return attr
def addJointArrayAttr(obj): ''' .. todo:: Eventually this should be abstracted. ''' mobj = core.capi.asMObject(obj) cAttr = OpenMaya.MFnCompoundAttribute() mList = cAttr.create('joints', 'jnts') cAttr.array = True mAttr = OpenMaya.MFnMessageAttribute() jMsg = mAttr.create('jmsg', 'jmsg') cAttr.addChild(jMsg) mobj.addAttribute(mList)
def initialize(): unitFn = om.MFnUnitAttribute() numericFn = om.MFnNumericAttribute() enumFn = om.MFnEnumAttribute() messageFn = om.MFnMessageAttribute() ######VECTOR drawVector.sourcePt = numericFn.createPoint('sourcePoint', 'sp') drawVector.aimPt = numericFn.createPoint('aimPoint', 'ap') drawVector.drawMessage = messageFn.create('drawMessage', 'drawMessage') drawVector.lineColor = numericFn.createColor('color', 'color') drawVector.lineWidth = numericFn.create('width', 'width', om.MFnNumericData.kFloat, 2.0) ######VECTOR om.MPxNode.addAttribute(drawVector.sourcePt) om.MPxNode.addAttribute(drawVector.aimPt) om.MPxNode.addAttribute(drawVector.drawMessage) om.MPxNode.addAttribute(drawVector.lineColor) om.MPxNode.addAttribute(drawVector.lineWidth)
def initialize(cls): nAttr = OpenMaya.MFnNumericAttribute() tAttr = OpenMaya.MFnTypedAttribute() enumAttr = OpenMaya.MFnEnumAttribute() compAttr = OpenMaya.MFnCompoundAttribute() matrixAttr = OpenMaya.MFnMatrixAttribute() messageAttr = OpenMaya.MFnMessageAttribute() cls.boundingBoxCorner1 = nAttr.create("boundingBoxCorner1", "bb1", OpenMaya.MFnNumericData.k3Double, 0) nAttr.keyable = False cls.addAttribute(cls.boundingBoxCorner1) cls.boundingBoxCorner2 = nAttr.create("boundingBoxCorner2", "bb2", OpenMaya.MFnNumericData.k3Double, 0) nAttr.keyable = False cls.addAttribute(cls.boundingBoxCorner2) cls.forgeID = tAttr.create("forgeID", "fid", OpenMaya.MFnData.kString, OpenMaya.MObject.kNullObj) cls.addAttribute(cls.forgeID) cls.handleMatrix = matrixAttr.create("handleMatrix", "hm", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.handleMatrix) cls.guideInverseScale = nAttr.create("guideInverseScale", "gis", OpenMaya.MFnNumericData.k3Double, 1.0) cls.addAttribute(cls.guideInverseScale) cls.guide = messageAttr.create("guide", "g") cls.addAttribute(cls.guide) cls.parentHandle = messageAttr.create("parentHandle", "ph") cls.addAttribute(cls.parentHandle) cls.parentHandleMatrix = matrixAttr.create("parentHandleMatrix", "phm", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.parentHandleMatrix) cls.childHandle = messageAttr.create("childHandle", "ch") messageAttr.array = True cls.addAttribute(cls.childHandle) cls.childHandleMatrix = matrixAttr.create("childHandleMatrix", "chm", OpenMaya.MFnMatrixAttribute.kDouble) matrixAttr.array = True cls.addAttribute(cls.childHandleMatrix) cls.orientTarget = messageAttr.create("orientTarget", "ot") cls.addAttribute(cls.orientTarget) cls.orientTargetMatrix = matrixAttr.create("orientTargetMatrix", "otm", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.orientTargetMatrix) cls.childPosition = nAttr.create("childPosition", "cpos", OpenMaya.MFnNumericData.k3Double, 0) nAttr.array = True nAttr.usesArrayDataBuilder = True cls.addAttribute(cls.childPosition) cls.jointRotateOrder = enumAttr.create("jointRotateOrder", "jro", 0) enumAttr.addField("xyz", 0) enumAttr.addField("yzx", 1) enumAttr.addField("zxy", 2) enumAttr.addField("xzy", 3) enumAttr.addField("yxz", 4) enumAttr.addField("zyx", 5) enumAttr.keyable = False cls.addAttribute(cls.jointRotateOrder) cls.jointSide = enumAttr.create("jointSide", "js", 0) enumAttr.addField("center", 0) enumAttr.addField("left", 1) enumAttr.addField("right", 2) enumAttr.addField("none", 3) enumAttr.keyable = True cls.addAttribute(cls.jointSide) cls.jointExcludeFromBind = nAttr.create("jointExcludeFromBind", "jeb", OpenMaya.MFnNumericData.kBoolean, 0) cls.addAttribute(cls.jointExcludeFromBind) cls.aimAxis = enumAttr.create("aimAxis", "aa", 0) enumAttr.addField("X", 0) enumAttr.addField("Y", 1) enumAttr.addField("Z", 2) enumAttr.addField("-X", 3) enumAttr.addField("-Y", 4) enumAttr.addField("-Z", 5) enumAttr.keyable = False cls.addAttribute(cls.aimAxis) cls.upAxis = enumAttr.create("upAxis", "ua", 2) enumAttr.addField("X", 0) enumAttr.addField("Y", 1) enumAttr.addField("Z", 2) enumAttr.addField("-X", 3) enumAttr.addField("-Y", 4) enumAttr.addField("-Z", 5) enumAttr.keyable = False cls.addAttribute(cls.upAxis) cls.aimVector = nAttr.create("aimVector", "av", OpenMaya.MFnNumericData.k3Double) cls.addAttribute(cls.aimVector) cls.upVector = nAttr.create("upVector", "uv", OpenMaya.MFnNumericData.k3Double) cls.addAttribute(cls.upVector) cls.useGuideAim = nAttr.create("useGuideAim", "uga", OpenMaya.MFnNumericData.kBoolean) cls.addAttribute(cls.useGuideAim) cls.jointMatrix = matrixAttr.create("jointMatrix", "jm", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.jointMatrix) cls.handleColor = nAttr.createColor("handleColor", "hc") cls.addAttribute(cls.handleColor) cls.handleStyle = enumAttr.create("handleStyle", "hs", 0) enumAttr.addField("basic", 0) enumAttr.addField("spine", 1) enumAttr.addField("limb", 2) enumAttr.addField("limb base", 3) enumAttr.addField("limb hinge", 4) enumAttr.addField("limb end", 5) enumAttr.addField("free", 6) enumAttr.addField("world", 7) cls.addAttribute(cls.handleStyle) cls.attributeAffects(cls.handleMatrix, cls.boundingBoxCorner1) cls.attributeAffects(cls.handleMatrix, cls.boundingBoxCorner2) cls.attributeAffects(cls.handleMatrix, cls.childPosition) cls.attributeAffects(cls.childHandleMatrix, cls.boundingBoxCorner1) cls.attributeAffects(cls.childHandleMatrix, cls.boundingBoxCorner2) cls.attributeAffects(cls.childHandleMatrix, cls.childPosition) cls.attributeAffects(cls.handleStyle, cls.boundingBoxCorner1) cls.attributeAffects(cls.handleStyle, cls.boundingBoxCorner2) cls.attributeAffects(cls.handleMatrix, cls.jointMatrix) cls.attributeAffects(cls.orientTargetMatrix, cls.jointMatrix) cls.attributeAffects(cls.parentHandleMatrix, cls.jointMatrix) cls.attributeAffects(cls.aimAxis, cls.jointMatrix) cls.attributeAffects(cls.upAxis, cls.jointMatrix) cls.attributeAffects(cls.aimVector, cls.jointMatrix) cls.attributeAffects(cls.upVector, cls.jointMatrix) cls.attributeAffects(cls.useGuideAim, cls.jointMatrix)
def initialize(cls): nAttr = OpenMaya.MFnNumericAttribute() tAttr = OpenMaya.MFnTypedAttribute() uAttr = OpenMaya.MFnUnitAttribute() enumAttr = OpenMaya.MFnEnumAttribute() compAttr = OpenMaya.MFnCompoundAttribute() matrixAttr = OpenMaya.MFnMatrixAttribute() messageAttr = OpenMaya.MFnMessageAttribute() cls.forgeID = tAttr.create("forgeID", "fid", OpenMaya.MFnData.kString, OpenMaya.MObject.kNullObj) cls.addAttribute(cls.forgeID) cls.guideMatrix = matrixAttr.create( "guideMatrix", "gm", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.guideMatrix) cls.handleInverseScale = nAttr.create("handleInverseScale", "his", OpenMaya.MFnNumericData.k3Double, 1.0) cls.addAttribute(cls.handleInverseScale) cls.boundingBoxCorner1 = nAttr.create("boundingBoxCorner1", "bb1", OpenMaya.MFnNumericData.k3Double, 0) nAttr.keyable = False cls.addAttribute(cls.boundingBoxCorner1) cls.boundingBoxCorner2 = nAttr.create("boundingBoxCorner2", "bb2", OpenMaya.MFnNumericData.k3Double, 0) nAttr.keyable = False cls.addAttribute(cls.boundingBoxCorner2) cls.aimAxis = enumAttr.create("aimAxis", "aa", 0) enumAttr.addField("X", 0) enumAttr.addField("Y", 1) enumAttr.addField("Z", 2) enumAttr.addField("-X", 3) enumAttr.addField("-Y", 4) enumAttr.addField("-Z", 5) enumAttr.keyable = False cls.addAttribute(cls.aimAxis) cls.upAxis = enumAttr.create("upAxis", "ua", 2) enumAttr.addField("X", 0) enumAttr.addField("Y", 1) enumAttr.addField("Z", 2) enumAttr.addField("-X", 3) enumAttr.addField("-Y", 4) enumAttr.addField("-Z", 5) enumAttr.keyable = False cls.addAttribute(cls.upAxis) cls.aimVector = nAttr.create("aimVector", "av", OpenMaya.MFnNumericData.k3Double) cls.addAttribute(cls.aimVector) cls.upVector = nAttr.create("upVector", "uv", OpenMaya.MFnNumericData.k3Double) cls.addAttribute(cls.upVector) cls.provideAimVector = nAttr.create("provideAimVector", "pav", OpenMaya.MFnNumericData.kBoolean, 0) cls.addAttribute(cls.provideAimVector) cls.handle = messageAttr.create("handle", "hndl") messageAttr.array = True cls.addAttribute(cls.handle) cls.handleColor = nAttr.createColor("handleColor", "hc") cls.addAttribute(cls.handleColor) cls.parentGuide = messageAttr.create("parentGuide", "pg") cls.addAttribute(cls.parentGuide) cls.parentGuideHandleIndex = nAttr.create( "parentGuideHandleIndex", "pghi", OpenMaya.MFnNumericData.kShort, -1) cls.addAttribute(cls.parentGuideHandleIndex) cls.childGuide = messageAttr.create("childGuide", "cg") cls.addAttribute(cls.childGuide) cls.attributeAffects(cls.guideMatrix, cls.boundingBoxCorner1) cls.attributeAffects(cls.guideMatrix, cls.boundingBoxCorner2) cls.attributeAffects(cls.guideMatrix, cls.handleInverseScale) cls.attributeAffects(cls.guideMatrix, cls.aimVector) cls.attributeAffects(cls.guideMatrix, cls.upVector)
class Plug(object): ''' Helper class to allow seamless value assignment from one plug to another, while correctly handling and abstracting away plug type. "self.type" returns the type of the plug. This is necessary to determine how to read and write the plug. "self.value" returns the value of the plug. "self.value = otherValue" will set the value of the plug to otherValue. This mutator assumes otherValue to be the same type as self.type "self.overrideType" returns the type of the override that should be created to override this plug. ''' # Plug types kInvalid = 0 kFloat = 1 kDouble = 2 kInt = 3 kByte = 4 kBool = 5 kColor = 6 kEnum = 7 kString = 8 kObject = 9 kMessage = 10 kTime = 11 kAngle = 12 kDistance = 13 kArray = 14 kLast = 15 _simpleOvrSupportedTypes = set([ kFloat, kDouble, kInt, kByte, kBool, kColor, kEnum, kString, kTime, kAngle, kDistance ]) _simpleNumericTypes = set( [kFloat, kDouble, kInt, kByte, kAngle, kDistance]) @staticmethod def _isVector(type): # type is a vector type if it's a list and it has 2 or 3 homogeneous "simple numeric" elements # kTime is deliberately excluded, see create method in doc for explanation # http://help.autodesk.com/view/MAYAUL/2016/ENU/?guid=__cpp_ref_class_m_fn_numeric_attribute_html return isinstance(type, list) and len(type) <= 3 and (len( set(type)) == 1) and type[0] in Plug._simpleNumericTypes @staticmethod def _isOvrSupported(type): return Plug._isVector(type) if isinstance( type, list) else type in Plug._simpleOvrSupportedTypes _accessors = { kInvalid: lambda plug: None, kFloat: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asFloat), kDouble: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asDouble), kInt: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asInt), kBool: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asBool), kByte: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asChar), kColor: lambda plug: plug._getCompound(), kEnum: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asShort), kString: lambda plug: plug._getPlugValue(OpenMaya.MPlug.asString), kObject: lambda plug: plug._getObject(), kMessage: lambda plug: None, kTime: lambda plug: plug._getTime(), kAngle: lambda plug: plug._getPlugValue( OpenMaya.MPlug.asDouble), # get the value in internal units kDistance: lambda plug: plug._getPlugValue( OpenMaya.MPlug.asDouble), # get the value in internal units kArray: lambda plug: plug._getArray() } @staticmethod def _accessor(type): return (lambda plug: plug._getCompound()) if isinstance( type, list) else Plug._accessors[type] _mutators = { kInvalid: lambda plug, value: None, kFloat: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueFloat, value), kDouble: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueDouble, value), kInt: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueInt, int(round(value))), kBool: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueBool, bool(round(value))), kByte: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueChar, int(round(value))), kColor: lambda plug, value: plug._setCompound(value), kEnum: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueInt, int(round(value))), kString: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueString, value), kObject: lambda plug, value: plug._setObject(value), kMessage: lambda plug, value: None, kTime: lambda plug, value: plug._setTime(value), kAngle: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueDouble, value ), # set the value in internal units kDistance: lambda plug, value: plug._setPlugValue( OpenMaya.MDGModifier.newPlugValueDouble, value ), # set the value in internal units kArray: lambda plug, value: plug._setArray(value) } @staticmethod def _mutator(type): return (lambda plug, value: plug._setCompound(value)) if isinstance( type, list) else Plug._mutators[type] _creators = { kFloat: (OpenMaya.MFnNumericAttribute, lambda longName, shortName: OpenMaya.MFnNumericAttribute().create( longName, shortName, OpenMaya.MFnNumericData.kFloat)), kDouble: (OpenMaya.MFnNumericAttribute, lambda longName, shortName: OpenMaya.MFnNumericAttribute().create( longName, shortName, OpenMaya.MFnNumericData.kDouble)), kInt: (OpenMaya.MFnNumericAttribute, lambda longName, shortName: OpenMaya.MFnNumericAttribute( ).create(longName, shortName, OpenMaya.MFnNumericData.kInt)), kBool: (OpenMaya.MFnNumericAttribute, lambda longName, shortName: OpenMaya.MFnNumericAttribute(). create(longName, shortName, OpenMaya.MFnNumericData.kBoolean)), kByte: (OpenMaya.MFnNumericAttribute, lambda longName, shortName: OpenMaya.MFnNumericAttribute( ).create(longName, shortName, OpenMaya.MFnNumericData.kChar)), kColor: (OpenMaya.MFnNumericAttribute, lambda longName, shortName: OpenMaya. MFnNumericAttribute().createColor(longName, shortName)), kEnum: (OpenMaya.MFnEnumAttribute, lambda longName, shortName: OpenMaya .MFnEnumAttribute().create(longName, shortName)), kString: (OpenMaya.MFnTypedAttribute, lambda longName, shortName: OpenMaya.MFnTypedAttribute( ).create(longName, shortName, OpenMaya.MFnData.kString)), kMessage: (OpenMaya.MFnMessageAttribute, lambda longName, shortName: OpenMaya.MFnMessageAttribute().create(longName, shortName)), kTime: (OpenMaya.MFnUnitAttribute, lambda longName, shortName: OpenMaya.MFnUnitAttribute().create( longName, shortName, OpenMaya.MFnUnitAttribute.kTime)), kAngle: (OpenMaya.MFnUnitAttribute, lambda longName, shortName: OpenMaya.MFnUnitAttribute().create( longName, shortName, OpenMaya.MFnUnitAttribute.kAngle)), kDistance: (OpenMaya.MFnUnitAttribute, lambda longName, shortName: OpenMaya.MFnUnitAttribute().create( longName, shortName, OpenMaya.MFnUnitAttribute.kDistance)), kObject: (None, None), kArray: (None, None) } @staticmethod def _creator(type): if isinstance(type, list): # compound type -> create a recursive creator childrenCreators = [Plug._creator(t) for t in type] def creator(longName, shortName): children = [ creator(longName + str(i), shortName + str(i)) for (i, (fnclass, creator)) in enumerate(childrenCreators) ] if Plug._isVector(type): # special case for compound of homogeneous numeric or unit types # using MFnCompoundAttribute is not enough as maya won't create # unitConversion nodes on plug parent on connection in this case # We need to create a MFnNumericAttribute to solve that args = [longName, shortName] + children obj = OpenMaya.MFnNumericAttribute().create(*args) else: obj = OpenMaya.MFnCompoundAttribute().create( longName, shortName) attr = OpenMaya.MFnCompoundAttribute(obj) for child in children: attr.addChild(child) return obj return (OpenMaya.MFnCompoundAttribute, creator) return Plug._creators[type] _numericToPlugTypes = { OpenMaya.MFnNumericData.kFloat: kFloat, OpenMaya.MFnNumericData.kDouble: kDouble, OpenMaya.MFnNumericData.kInt: kInt, OpenMaya.MFnNumericData.kShort: kInt, OpenMaya.MFnNumericData.kLong: kInt, OpenMaya.MFnNumericData.kBoolean: kBool, OpenMaya.MFnNumericData.kByte: kByte, OpenMaya.MFnNumericData.kChar: kByte, } _unitToPlugTypes = { OpenMaya.MFnUnitAttribute.kTime: kTime, OpenMaya.MFnUnitAttribute.kAngle: kAngle, OpenMaya.MFnUnitAttribute.kDistance: kDistance } # MAYA-66685: remove this table and its associated static function (below) # it won't be needed anymore when we remove relative override's children classes # and adapt the overrideType(self, overrideType) method accordingly _typesToOverrideTypes = { kFloat: [typeIDs.absOverride, typeIDs.relOverride], kDouble: [typeIDs.absOverride, typeIDs.relOverride], kInt: [typeIDs.absOverride, typeIDs.relOverride], kBool: [typeIDs.absOverride, typeIDs.absOverride], kByte: [typeIDs.absOverride, typeIDs.relOverride], kColor: [typeIDs.absOverride, typeIDs.relOverride], kEnum: [typeIDs.absOverride, typeIDs.absOverride], kString: [typeIDs.absOverride, typeIDs.absOverride], kTime: [typeIDs.absOverride, typeIDs.relOverride], kAngle: [typeIDs.absOverride, typeIDs.relOverride], kDistance: [typeIDs.absOverride, typeIDs.relOverride] } @staticmethod def _typeToOverrideType(type): vecDict = { 2: [typeIDs.absOverride, typeIDs.relOverride], 3: [typeIDs.absOverride, typeIDs.relOverride] } return vecDict[len(type)] if Plug._isVector( type) else Plug._typesToOverrideTypes[type] _typesToApplyOverrideTypes = { kFloat: [typeIDs.applyAbsFloatOverride, typeIDs.applyRelFloatOverride], kDouble: [typeIDs.applyAbsFloatOverride, typeIDs.applyRelFloatOverride], kInt: [typeIDs.applyAbsIntOverride, typeIDs.applyRelIntOverride], kBool: [typeIDs.applyAbsBoolOverride, typeIDs.applyAbsBoolOverride], kByte: [typeIDs.applyAbsIntOverride, typeIDs.applyRelIntOverride], kColor: [typeIDs.applyAbs3FloatsOverride, typeIDs.applyRel3FloatsOverride], kEnum: [typeIDs.applyAbsEnumOverride, typeIDs.applyAbsEnumOverride], kString: [typeIDs.applyAbsStringOverride, typeIDs.applyAbsStringOverride], kTime: [typeIDs.applyAbsFloatOverride, typeIDs.applyRelFloatOverride], kAngle: [typeIDs.applyAbsFloatOverride, typeIDs.applyRelFloatOverride], kDistance: [typeIDs.applyAbsFloatOverride, typeIDs.applyRelFloatOverride] } @staticmethod def _typeToApplyOverrideType(type): vecDict = { 2: [typeIDs.applyAbs2FloatsOverride, typeIDs.applyRel2FloatsOverride], 3: [typeIDs.applyAbs3FloatsOverride, typeIDs.applyRel3FloatsOverride] } return vecDict[len(type)] if Plug._isVector( type) else Plug._typesToApplyOverrideTypes[type] _typesToStrings = { kInvalid: "Invalid", kFloat: "Float", kDouble: "Double", kInt: "Int", kByte: "Byte", kBool: "Bool", kColor: "Color", kEnum: "Enum", kString: "String", kObject: "Object", kMessage: "Message", kTime: "Time", kAngle: "Angle", kDistance: "Distance", kArray: "Array" } @staticmethod def _typeToString(type): return [Plug._typeToString(t) for t in type] if isinstance( type, list) else Plug._typesToStrings[type] _stringsToTypes = {v: k for k, v in _typesToStrings.items()} @staticmethod def _stringToType(string): return [Plug._stringToType(s) for s in string] if isinstance( string, list) else Plug._stringsToTypes[string] _typesToLocalizedStrings = { kInvalid: maya.stringTable['y_plug.kInvalid'], kFloat: maya.stringTable['y_plug.kFloat'], kDouble: maya.stringTable['y_plug.kDouble'], kInt: maya.stringTable['y_plug.kInt'], kByte: maya.stringTable['y_plug.kByte'], kBool: maya.stringTable['y_plug.kBool'], kColor: maya.stringTable['y_plug.kColor'], kEnum: maya.stringTable['y_plug.kEnum'], kString: maya.stringTable['y_plug.kString'], kObject: maya.stringTable['y_plug.kObject'], kMessage: maya.stringTable['y_plug.kMessage'], kTime: maya.stringTable['y_plug.kTime'], kAngle: maya.stringTable['y_plug.kAngle'], kDistance: maya.stringTable['y_plug.kDistance'], kArray: maya.stringTable['y_plug.kArray'] } @staticmethod def _typeToLocalizedString(type): if isinstance(type, list): return kCompoundTypeStr if not Plug._isVector(type) else \ kVectorTypeStr % (len(type), Plug._typesToLocalizedStrings[type[0]]) return Plug._typesToLocalizedStrings[type] # Types with a function set supporting min/max limits _limitTypes = set([kFloat, kDouble, kInt, kByte, kTime, kAngle, kDistance]) @staticmethod def _hasLimits(type): return not isinstance(type, list) and type in Plug._limitTypes def __init__(self, plugOrNode, attrName=None): """ Constructors: Plug(MPlug) Plug(string (full plug name)) Plug(MObject, MObject) Plug(MObject, string (attribute name)) Plug(string (node name), string (attribute name)) """ if isinstance(plugOrNode, OpenMaya.MPlug): # Plug(MPlug) self._plug = plugOrNode elif attrName is None: self._plug = commonUtils.nameToPlug(plugOrNode) else: self._plug = commonUtils.findPlug(plugOrNode, attrName) if self._plug is not None: # There is no consistency around the node name (i.e. child node names) # and the attribute name (i.e. long vs. short names and compound names) # between the various API methods. To avoid different names, Plug is now always using # the same API methods. self._nodeName = commonUtils.nodeToLongName(self._plug.node()) self._attributeName = self._plug.partialName( includeInstancedIndices=True, useLongNames=True) self._name = self._nodeName + '.' + self._attributeName self._type = None if self._plug else Plug.kInvalid def copyValue(self, other): """ Sets the value of plug 'self' to the value contained in plug 'other' The 'other' plug can be either a Plug or a MPlug. """ # MAYA-66652: more tests with generic attributes vs non generic attributes copies if isinstance(other, OpenMaya.MPlug): other = Plug(other) if other.plug.isCompound and not self.plug.isCompound: # We cannot do recursive get/set since 'self' has no children # Try to read 'other' as MObject and set it to dst # This is valid for example if 'self' is generic and accepts 'other' data type self._type = Plug.kObject self.value = other._getObject() else: self.uiUnitValue = other.uiUnitValue @staticmethod def getNames(plugName): pos = plugName.find('.') return (plugName[:pos], plugName[pos + 1:]) @property def name(self): return self._name @property def attributeName(self): return self._attributeName @property def nodeName(self): return self._nodeName @property def plug(self): return self._plug def node(self): return self._plug.node() def isOvrSupported(self): return Plug._isOvrSupported(self.type) def overrideType(self, overType): if not self.isOvrSupported(): raise RuntimeError( kNotOverridablePlug % (self.plug.name(), str(Plug._typeToString(self.type)))) return Plug._typeToOverrideType( self.type)[0 if overType == typeIDs.absOverride else 1] def applyOverrideType(self, overType): if not self.isOvrSupported(): raise RuntimeError( kNotOverridablePlug % (self.plug.name(), str(Plug._typeToString(self.type)))) return Plug._typeToApplyOverrideType( self.type)[0 if overType == typeIDs.absOverride else 1] @property def uiUnitValue(self): return toUiUnits(self.type, self.value) @uiUnitValue.setter def uiUnitValue(self, value): self.value = toInternalUnits(self.type, value) @property def value(self): return Plug._accessor(self.type)(self) @value.setter def value(self, value): # Check that plug parent and children are settable. # Otherwise the DGModifier fails to write value plug = self.plug if plug.isChild and plug.parent().isDestination: raise RuntimeError(kPlugHasConnectedParent % self.name) if plug.isCompound and plug.numConnectedChildren() != 0: for i in range(0, self.plug.numChildren()): if not isSettable(self.plug.child(i)): raise RuntimeError(kPlugHasNotSettableChild % self.name) Plug._mutator(self.type)(self, value) def parent(self): return Plug(self.plug.parent()) if self.plug.isChild else None def children(self): if not self.plug.isCompound: return for i in xrange(0, self.plug.numChildren()): yield Plug(self.plug.child(i)) @property def type(self): # Lazy evaluate if self._type is None: plug = self.plug attr = plug.attribute() if attr.hasFn(OpenMaya.MFn.kMessageAttribute): self._type = Plug.kMessage elif plug.isArray: self._type = Plug.kArray elif attr.hasFn(OpenMaya.MFn.kCompoundAttribute): self._type = Plug.kColor if OpenMaya.MFnAttribute(attr).usedAsColor else \ [ child.type for child in self._children() ] elif attr.hasFn(OpenMaya.MFn.kNumericAttribute): self._type = Plug._numericToPlugTypes.get( OpenMaya.MFnNumericAttribute(attr).numericType(), Plug.kInvalid) elif attr.hasFn(OpenMaya.MFn.kTypedAttribute): dataType = OpenMaya.MFnTypedAttribute(attr).attrType() if dataType == OpenMaya.MFnData.kString: self._type = Plug.kString else: self._type = Plug.kInvalid elif attr.hasFn(OpenMaya.MFn.kEnumAttribute): self._type = Plug.kEnum elif attr.hasFn(OpenMaya.MFn.kUnitAttribute): self._type = Plug._unitToPlugTypes.get( OpenMaya.MFnUnitAttribute(attr).unitType(), Plug.kInvalid) elif attr.hasFn(OpenMaya.MFn.kGenericAttribute): handle = plug.asMDataHandle() isGeneric, isGenericNumeric, isGenericNull = handle.isGeneric() if isGeneric and isGenericNumeric: # It's a generic simple attribute. # According to docs there is no method to check the type # of a generic simple attribute: # http://help.autodesk.com/view/MAYAUL/2016/ENU/?guid=__cpp_ref_class_m_data_handle_html # So always return as double here self._type = Plug.kDouble elif not isGenericNull: obj = handle.data() if obj.hasFn(OpenMaya.MFn.kStringData): self._type = Plug.kString else: # if handle.data() didn't raise an exception, # plug can be read as MObject self._type = Plug.kObject else: raise RuntimeError(kUnknownType % self.name) else: raise RuntimeError(kUnsupportedAttribute % self.name) return self._type @property def isValid(self): return self.type != Plug.kInvalid def localizedTypeString(self): return Plug._typeToLocalizedString(self.type) @property def isLocked(self): """Returns true is plug or plug's children (compound) are locked.""" plug = self.plug if plug.isLocked: return True elif plug.isCompound: for i in range(0, plug.numChildren()): if Plug(plug.child(i)).isLocked: return True return False @property def isConnectable(self): """Returns true if plug's input can be connected.""" if not self.attribute().connectable: return False plug = self.plug if plug.isCompound: for i in range(0, plug.numChildren()): if not Plug(plug.child(i)).isConnectable: return False return True @property def isKeyable(self): """Returns true if the plug has the keyable property. Note that a plug that does not have this property can still have key frames set on it. As per Maya documentation, a keyable attribute means that 'if any of the animation commands (setKeyframe, cutKey, copyKey,..) are issued without explicitly specifying any attributes with the -at/attribute flag, then the command will operate on all keyable attributes of the specified objects'. The autoKeyframe functionality also uses the keyable property to determine if key frames should be set.""" return self.attribute().keyable def attribute(self): """Returns the attribute (MFnAttribute) of the plug """ return OpenMaya.MFnAttribute(self.plug.attribute()) def accepts(self, other): """Returns true if plug would accept a connection with other plug i.e. plug and other plug are type compatible for connection.""" if isinstance(other, OpenMaya.MPlug): other = Plug(other) return self.attribute().acceptsAttribute(other.attribute()) @property def isVector(self): """ Returns true if the type is a vector type. """ return Plug._isVector(self.type) @property def isUnit(self): return self._plug.attribute().hasFn(OpenMaya.MFn.kUnitAttribute) @property def isNumeric(self): return self._plug.attribute().hasFn(OpenMaya.MFn.kNumericAttribute) @property def hasLimits(self): """ Returns true if the type supports min/max limits. """ return Plug._hasLimits(self.type) # specialized GETS and SETS def _setPlugValue(self, method, value): """ Sets the value of the plug to value, using DGModifier specified method """ dgMod = OpenMaya.MDGModifier() method(dgMod, self.plug, value) dgMod.doIt() def _getPlugValue(self, method): """ Gets the value of the plug using MPlug specified method """ return method(self.plug) if not self.plug.isNull else None def _children(self): children = [ Plug(self.plug.child(i)) for i in range(0, self.plug.numChildren()) ] if isinstance(self._type, list): # avoid recompute types for children if we already know it from the parent for child, t in itertools.izip(children, self.type): child._type = t return children def _getCompound(self): return [child.value for child in self._children()] def _setCompound(self, value): children = self._children() if len(children) != len(value): raise RuntimeError(kArityMismatch % (self.name, len(children), len(value))) for child, val in itertools.izip(children, value): child.value = val def _getObject(self): return self._getPlugValue(OpenMaya.MPlug.asMObject) def _setObject(self, value): self._setPlugValue(OpenMaya.MDGModifier.newPlugValue, value) def _getTime(self): return self._getPlugValue(OpenMaya.MPlug.asMTime).asUnits( OpenMaya.MTime.k6000FPS) # internal time units def _setTime(self, value): """ Sets plug's value to the given time If value is a MTime, set's it directly Otherwise, assumes value is given in the same units as the plug's unit type.""" time = value if isinstance(value, OpenMaya.MTime) \ else OpenMaya.MTime(value, OpenMaya.MTime.k6000FPS) # internal time units self._setPlugValue(OpenMaya.MDGModifier.newPlugValueMTime, time) def _getArray(self): elements = [] plug = self.plug for i in range(0, plug.numElements()): elements.append(Plug(plug.elementByLogicalIndex(i)).value) return elements def _setArray(self, value): plug = self.plug n = len(value) # clear remaining elements if any dgMod = OpenMaya.MDGModifier() for i in range(n, plug.numElements()): dgMod.removeMultiInstance(plug.elementByLogicalIndex(i), False) dgMod.doIt() # fill array with new values plug.setNumElements(n) for i in range(0, n): Plug(plug.elementByLogicalIndex(i)).value = value[i] def __str__(self): return self.name + " (" + Plug._typeToLocalizedString( self.type) + ") = " + str(self.value) @staticmethod def createAttribute(nodeObj, longName, shortName, dict, undoable=kUndoable): """ Create a new attribute on a node using the given names and properties dictionary. Returns an MObject to the new attribute. By default, it uses the command addDynamicAttribute (if it's not undoable, use MFnDependencyNode.addAttribute()) to add the returned object as a new dynamic attribute on a node. """ if 'type' not in dict: return None plugType = Plug._stringToType(dict['type']) fnclass, create = Plug._creator(plugType) if not (fnclass and create): return None # Create the attribute and add it to the node with a command if undoable # Use the DGModifier if not attrObj = create(longName, shortName) if undoable == kUndoable: AddDynamicAttribute.execute(nodeObj, attrObj) else: nodeFn = OpenMaya.MFnDependencyNode(nodeObj) nodeFn.addAttribute(attrObj) # Set all properties from the dictionary plg = Plug(nodeObj, attrObj) plg._decodeProperties(dict) return plg def _createAttribute(self, nodeObj, longName, shortName, dict, undoable=kUndoable): """See createAttribute documentation for details. This method calls createAttribute. If the created attribute is a compound, it additionally copies over the keyable property from the original's children to the copy's children.""" copy = Plug.createAttribute(nodeObj, longName, shortName, dict, undoable) if copy.plug.isCompound: for i in xrange(0, copy.plug.numChildren()): copy.plug.child(i).isKeyable = self.plug.child(i).isKeyable return copy def cloneAttribute(self, nodeObj, longName, shortName, undoable=kUndoable): """ Creates a new attribute on a node by cloning this plug's attribute. Undoable by default """ dict = {} self._encodeProperties(dict) return self._createAttribute(nodeObj, longName, shortName, dict, undoable) def createAttributeFrom(self, nodeObj, longName, shortName, limits=None): """ Creates a new attribute on a node by cloning this plug's attribute. Note: None for a limit value means that there is no limit. For example, if min is None, it means that there is no minimum limit. """ dict = {} self._encodeProperties(dict) # Adjust the limits if limits is not None: for (key, value) in limits.items(): if value is not None: dict[key] = value elif key in dict: del dict[key] return self._createAttribute(nodeObj, longName, shortName, dict) def getAttributeLimits(self): """ Get the limits of the plug """ if self.hasLimits: def _get(f, unit): return f().value if unit else f() unit = self.isUnit cls = OpenMaya.MFnUnitAttribute if unit else OpenMaya.MFnNumericAttribute fn2 = cls(self._plug.attribute()) limits = dict() limits['min'] = _get(fn2.getMin, unit) if fn2.hasMin() else None limits['softMin'] = _get(fn2.getSoftMin, unit) if fn2.hasSoftMin() else None limits['softMax'] = _get(fn2.getSoftMax, unit) if fn2.hasSoftMax() else None limits['max'] = _get(fn2.getMax, unit) if fn2.hasMax() else None return limits else: raise RuntimeError(kPlugWithoutLimits % self.plug.name()) def _encodeProperties(self, dict): """ Encode the properties of this plug's attribute into a dictionary. """ fn = OpenMaya.MFnAttribute(self._plug.attribute()) dict['type'] = Plug._typeToString(self.type) dict['connectable'] = fn.connectable if fn.keyable: dict['keyable'] = True val = self.value if val is not None: dict['value'] = val if self.hasLimits: limits = self.getAttributeLimits() # There is no need to save None values for (key, value) in limits.items(): if value is not None: dict[key] = value if self.type == Plug.kEnum: fn2 = OpenMaya.MFnEnumAttribute(self._plug.attribute()) enum = {} for val in range(fn2.getMin(), fn2.getMax() + 1): try: # Need to catch exception here because all values in # range min -> max are not always used, but there is no # way to query the attribute if a value is used or not. # An exception is raised if a value is not used. enum[val] = fn2.fieldName(val) except: pass dict['enum'] = enum def setAttributeLimits(self, limits): if self.hasLimits: fnclass, create = Plug._creator(self.type) fn = fnclass(self._plug.attribute()) setters = { 'min': fn.setMin, 'softMin': fn.setSoftMin, 'softMax': fn.setSoftMax, 'max': fn.setMax } for (key, value) in limits.items(): if value is not None: setters[key](value) else: raise RuntimeError(kPlugWithoutLimits % self.plug.name()) def _decodeProperties(self, dict): """ Decode and set the properties from the given dictionary. """ plugType = Plug._stringToType(dict['type']) fnclass, create = Plug._creator(plugType) if not (fnclass and create): return None fn = fnclass(self._plug.attribute()) fn.connectable = dict['connectable'] if 'keyable' in dict: fn.keyable = dict['keyable'] if self.hasLimits: # To ease the manipulation, the limit keywords for the limits and the properties # are the same. But keep in mind that they are indepdendent. self.setAttributeLimits({ 'min': float(dict['min']) if 'min' in dict else None, 'softMin': float(dict['softMin']) if 'softMin' in dict else None, 'softMax': float(dict['softMax']) if 'softMax' in dict else None, 'max': float(dict['max']) if 'max' in dict else None }) if plugType == Plug.kEnum and 'enum' in dict: enum = dict['enum'] for val, name in enum.iteritems(): fn.addField(name, int(val)) # Set the value if a value is available. For attributes that don't have # values, e.g. message attributes, we don't encode any value. if 'value' in dict: self.value = dict['value']
def nodeInitializer(): ''' Defines the input and output attributes as static variables in our plug-in class. ''' # The following function set will allow us to create our attributes. numericAttributeFn = OpenMaya.MFnNumericAttribute() typedAttributeFn = OpenMaya.MFnTypedAttribute() messageAttributeFn = OpenMaya.MFnMessageAttribute() compoundAttributeFn = OpenMaya.MFnCompoundAttribute() #==================================# # INPUT NODE ATTRIBUTE(S) # #==================================# #-----------------------------------------# # Focus Iris Zoom # #-----------------------------------------# mFIZ_remap.focus_in_attr = numericAttributeFn.create( 'focus', 'focus', OpenMaya.MFnNumericData.kFloat) numericAttributeFn.writable = True numericAttributeFn.storable = True numericAttributeFn.hidden = False numericAttributeFn.setMin(0) numericAttributeFn.setMax(1) mFIZ_remap.addAttribute(mFIZ_remap.focus_in_attr) mFIZ_remap.iris_in_attr = numericAttributeFn.create( 'iris', 'iris', OpenMaya.MFnNumericData.kFloat) numericAttributeFn.writable = True numericAttributeFn.storable = True numericAttributeFn.hidden = False numericAttributeFn.setMin(0) numericAttributeFn.setMax(1) mFIZ_remap.addAttribute(mFIZ_remap.iris_in_attr) mFIZ_remap.zoom_in_attr = numericAttributeFn.create( 'zoom', 'zoom', OpenMaya.MFnNumericData.kFloat) numericAttributeFn.writable = True numericAttributeFn.storable = True numericAttributeFn.hidden = False numericAttributeFn.setMin(0) numericAttributeFn.setMax(1) mFIZ_remap.addAttribute(mFIZ_remap.zoom_in_attr) #==================================# # OUTPUT NODE ATTRIBUTE(S) # #==================================# mFIZ_remap.focus_out_attr = numericAttributeFn.create( 'focusMapped', 'focusMapped', OpenMaya.MFnNumericData.kInt, 0) numericAttributeFn.writable = False numericAttributeFn.storable = False numericAttributeFn.readable = True numericAttributeFn.hidden = False mFIZ_remap.addAttribute(mFIZ_remap.focus_out_attr) mFIZ_remap.iris_out_attr = numericAttributeFn.create( 'irisMapped', 'irisMapped', OpenMaya.MFnNumericData.kInt, 0) numericAttributeFn.writable = False numericAttributeFn.storable = False numericAttributeFn.readable = True numericAttributeFn.hidden = False mFIZ_remap.addAttribute(mFIZ_remap.iris_out_attr) mFIZ_remap.zoom_out_attr = numericAttributeFn.create( 'zoomMapped', 'zoomMapped', OpenMaya.MFnNumericData.kInt, 0) numericAttributeFn.writable = False numericAttributeFn.storable = False numericAttributeFn.readable = True numericAttributeFn.hidden = False mFIZ_remap.addAttribute(mFIZ_remap.zoom_out_attr) #===================================# # NODE ATTRIBUTE DEPENDENCIES # #===================================# input_attrs = [ mFIZ_remap.focus_in_attr, mFIZ_remap.iris_in_attr, mFIZ_remap.zoom_in_attr ] output_attrs = [ mFIZ_remap.focus_out_attr, mFIZ_remap.iris_out_attr, mFIZ_remap.zoom_out_attr ] for input_attr in input_attrs: for output_attr in output_attrs: mFIZ_remap.attributeAffects(input_attr, output_attr)
def nodeInitializer(): ''' Defines the input and output attributes as static variables in our plug-in class. ''' # The following function set will allow us to create our attributes. numericAttributeFn = OpenMaya.MFnNumericAttribute() typedAttributeFn = OpenMaya.MFnTypedAttribute() messageAttributeFn = OpenMaya.MFnMessageAttribute() compoundAttributeFn = OpenMaya.MFnCompoundAttribute() #==================================# # INPUT NODE ATTRIBUTE(S) # #==================================# #-----------------------------------------# # Focus Iris Zoom # #-----------------------------------------# mFIZ.focus_attr = numericAttributeFn.create('focus', 'focus', OpenMaya.MFnNumericData.kFloat) numericAttributeFn.writable = True numericAttributeFn.storable = True numericAttributeFn.hidden = False numericAttributeFn.setMin(0) numericAttributeFn.setMax(1) mFIZ.addAttribute(mFIZ.focus_attr) mFIZ.iris_attr = numericAttributeFn.create('iris', 'iris', OpenMaya.MFnNumericData.kFloat) numericAttributeFn.writable = True numericAttributeFn.storable = True numericAttributeFn.hidden = False numericAttributeFn.setMin(0) numericAttributeFn.setMax(1) mFIZ.addAttribute(mFIZ.iris_attr) mFIZ.zoom_attr = numericAttributeFn.create('zoom', 'zoom', OpenMaya.MFnNumericData.kFloat) numericAttributeFn.writable = True numericAttributeFn.storable = True numericAttributeFn.hidden = False numericAttributeFn.setMin(0) numericAttributeFn.setMax(1) mFIZ.addAttribute(mFIZ.zoom_attr) #-----------------------------------------# # Connection # #-----------------------------------------# mFIZ.live_attr = numericAttributeFn.create( 'live', 'live', OpenMaya.MFnNumericData.kBoolean, 0) numericAttributeFn.writable = True numericAttributeFn.connectable = False numericAttributeFn.storable = False numericAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.live_attr) #-----------------------------------------# # Port Name # #-----------------------------------------# mFIZ.port_name_attr = typedAttributeFn.create('portName', 'portName', OpenMaya.MFnData.kString) typedAttributeFn.writable = True typedAttributeFn.connectable = False typedAttributeFn.storable = False typedAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.port_name_attr) #-----------------------------------------# # API Type # #-----------------------------------------# mFIZ.api_attr = typedAttributeFn.create('api', 'api', OpenMaya.MFnData.kString) typedAttributeFn.writable = True typedAttributeFn.storable = False typedAttributeFn.connectable = False typedAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.api_attr) ''' mFIZ.api_attr= numericAttributeFn.create('api', 'api', OpenMaya.MFnNumericData.kInt, 0) numericAttributeFn.writable = True numericAttributeFn.storable = False numericAttributeFn.connectable = False numericAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.api_attr) ''' #-----------------------------------------# # Stop Playback on Disconnect # #-----------------------------------------# mFIZ.stop_playback_on_disconnect_attr = numericAttributeFn.create( 'stopPlaybackOnDisconnect', 'stopPlaybackOnDisconnect', OpenMaya.MFnNumericData.kBoolean, 0) numericAttributeFn.writable = True numericAttributeFn.connectable = False numericAttributeFn.storable = True numericAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.stop_playback_on_disconnect_attr) #==================================# # OUTPUT NODE ATTRIBUTE(S) # #==================================# mFIZ.data_sent_attr = numericAttributeFn.create( 'dataSent', 'dataSent', OpenMaya.MFnNumericData.kBoolean, 0) numericAttributeFn.writable = False numericAttributeFn.storable = False numericAttributeFn.readable = True numericAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.data_sent_attr) mFIZ.controller_attr = messageAttributeFn.create('controller', 'controller') messageAttributeFn.writable = True messageAttributeFn.storable = True messageAttributeFn.hidden = False mFIZ.addAttribute(mFIZ.controller_attr) #===================================# # NODE ATTRIBUTE DEPENDENCIES # #===================================# input_attrs = [ mFIZ.focus_attr, mFIZ.iris_attr, mFIZ.zoom_attr, mFIZ.live_attr, mFIZ.api_attr, mFIZ.stop_playback_on_disconnect_attr ] output_attrs = [mFIZ.data_sent_attr] for input_attr in input_attrs: for output_attr in output_attrs: mFIZ.attributeAffects(input_attr, output_attr)
def addAttribute(node, longName, shortName, attrType=attrtypes.kMFnNumericDouble, isArray=False, apply=True): """This function uses the api to create attributes on the given node, currently WIP but currently works for string,int, float, bool, message, matrix. if the attribute exists a ValueError will be raised. :param node: MObject :param longName: str, the long name for the attribute :param shortName: str, the shortName for the attribute :param attrType: attribute Type, attrtypes constants :param apply: if False the attribute will be immediately created on the node else just return the attribute instance :rtype: om.MObject """ if hasAttribute(node, longName): raise ValueError("Node -> '%s' already has attribute -> '%s'" % (nameFromMObject(node), longName)) aobj = None attr = None if attrType == attrtypes.kMFnNumericDouble: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kDouble) elif attrType == attrtypes.kMFnNumericFloat: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kFloat) elif attrType == attrtypes.kMFnNumericBoolean: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kBoolean) elif attrType == attrtypes.kMFnNumericInt: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kInt) elif attrType == attrtypes.kMFnNumericShort: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kShort) elif attrType == attrtypes.kMFnNumericLong: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kLong) elif attrType == attrtypes.kMFnNumericByte: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kByte) elif attrType == attrtypes.kMFnNumericChar: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kChar) elif attrType == attrtypes.kMFnNumericAddr: attr = om2.MFnNumericAttribute() aobj = attr.createAddr(longName, shortName) elif attrType == attrtypes.kMFnkEnumAttribute: attr = om2.MFnEnumAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnCompoundAttribute: attr = om2.MFnCompoundAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnMessageAttribute: attr = om2.MFnMessageAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnDataString: attr = om2.MFnTypedAttribute() stringData = om2.MFnStringData().create("") aobj = attr.create(longName, shortName, om2.MFnData.kString, stringData) elif attrType == attrtypes.kMFnUnitAttributeDistance: attr = om2.MFnUnitAttribute() aobj = attr.create(longName, shortName, om2.MDistance()) elif attrType == attrtypes.kMFnUnitAttributeAngle: attr = om2.MFnUnitAttribute() aobj = attr.create(longName, shortName, om2.MAngle()) elif attrType == attrtypes.kMFnUnitAttributeTime: attr = om2.MFnUnitAttribute() aobj = attr.create(longName, shortName, om2.MTime()) elif attrType == attrtypes.kMFnDataMatrix: attr = om2.MFnMatrixAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnDataFloatArray: attr = om2.MFnFloatArray() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnDataDoubleArray: data = om2.MFnDoubleArrayData().create(om2.MDoubleArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kDoubleArray, data) elif attrType == attrtypes.kMFnDataIntArray: data = om2.MFnIntArrayData().create(om2.MIntArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kIntArray, data) elif attrType == attrtypes.kMFnDataPointArray: data = om2.MFnPointArrayData().create(om2.MPointArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kPointArray, data) elif attrType == attrtypes.kMFnDataVectorArray: data = om2.MFnVectorArrayData().create(om2.MVectorArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kVectorArray, data) elif attrType == attrtypes.kMFnDataStringArray: data = om2.MFnStringArrayData().create(om2.MStringArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kStringArray, data) elif attrType == attrtypes.kMFnDataMatrixArray: data = om2.MFnMatrixArrayData().create(om2.MMatrixArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kMatrixArray, data) elif attrType == attrtypes.kMFnNumericInt64: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kInt64) elif attrType == attrtypes.kMFnNumericLast: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kLast) elif attrType == attrtypes.kMFnNumeric2Double: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Double) elif attrType == attrtypes.kMFnNumeric2Float: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Float) elif attrType == attrtypes.kMFnNumeric2Int: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Int) elif attrType == attrtypes.kMFnNumeric2Long: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Long) elif attrType == attrtypes.kMFnNumeric2Short: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Short) elif attrType == attrtypes.kMFnNumeric3Double: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Double) elif attrType == attrtypes.kMFnNumeric3Float: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Float) elif attrType == attrtypes.kMFnNumeric3Int: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Int) elif attrType == attrtypes.kMFnNumeric3Long: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Long) elif attrType == attrtypes.kMFnNumeric3Short: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Short) elif attrType == attrtypes.kMFnNumeric4Double: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k4Double) if aobj is not None and apply: attr.array = isArray mod = om2.MDGModifier() mod.addAttribute(node, aobj) mod.doIt() return attr
def makePickwalkNode(ikControls=None, fkControls=None): ''' node.ikLinker[*].ikController .ikLeftIndexIk .ikLeftIndexFk .ikRightIndexIk .ikRightIndexFk ''' ikControls = ikControls if ikControls else [] fkControls = fkControls if fkControls else [] obj = createNode('network') obj.addAttr('up', at='message') obj.addAttr('down', at='message') obj.addAttr('switcher', at='double', dv=0) mobj = pdil.capi.asMObject(obj) for xk in ['ik', 'fk']: cattr = OpenMaya.MFnCompoundAttribute() mattr = OpenMaya.MFnMessageAttribute() nattr = OpenMaya.MFnNumericAttribute() controlLinker = cattr.create(xk + 'Linker', xk) cattr.array = True controller = mattr.create(xk + 'Controller', xk + 'ctrl') left = mattr.create(xk + 'Left', xk + 'l') right = mattr.create(xk + 'Right', xk + 'r') leftIndexIk = nattr.create(xk + 'LeftIndexIk', xk + 'lii', OpenMaya.MFnNumericData.kInt, -1) leftIndexFk = nattr.create(xk + 'LeftIndexFk', xk + 'lif', OpenMaya.MFnNumericData.kInt, -1) rightIndexIk = nattr.create(xk + 'RightIndexIk', xk + 'rii', OpenMaya.MFnNumericData.kInt, -1) rightIndexFk = nattr.create(xk + 'RightIndexFk', xk + 'rif', OpenMaya.MFnNumericData.kInt, -1) cattr.addChild(controller) cattr.addChild(left) cattr.addChild(right) cattr.addChild(leftIndexIk) cattr.addChild(leftIndexFk) cattr.addChild(rightIndexIk) cattr.addChild(rightIndexFk) mobj.addAttribute(controlLinker) for i, ctrl in enumerate(fkControls): print(ctrl, type(ctrl)) ctrl.message >> obj.fkLinker[i].fkController for i, ctrl in enumerate(ikControls): ctrl.message >> obj.ikLinker[i].ikController return obj
def initialize(cls): nAttr = OpenMaya.MFnNumericAttribute() tAttr = OpenMaya.MFnTypedAttribute() uAttr = OpenMaya.MFnUnitAttribute() enumAttr = OpenMaya.MFnEnumAttribute() compAttr = OpenMaya.MFnCompoundAttribute() matrixAttr = OpenMaya.MFnMatrixAttribute() messageAttr = OpenMaya.MFnMessageAttribute() cls.forgeID = tAttr.create("forgeID", "fid", OpenMaya.MFnData.kString, OpenMaya.MObject.kNullObj) cls.addAttribute(cls.forgeID) cls.guideMatrix = matrixAttr.create("guideMatrix", "gm", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.guideMatrix) cls.handleInverseScale = nAttr.create("handleInverseScale", "his", OpenMaya.MFnNumericData.k3Double, 1.0) cls.addAttribute(cls.handleInverseScale) cls.boundingBoxCorner1 = nAttr.create("boundingBoxCorner1", "bb1", OpenMaya.MFnNumericData.k3Double, 0) nAttr.keyable = False cls.addAttribute(cls.boundingBoxCorner1) cls.boundingBoxCorner2 = nAttr.create("boundingBoxCorner2", "bb2", OpenMaya.MFnNumericData.k3Double, 0) nAttr.keyable = False cls.addAttribute(cls.boundingBoxCorner2) cls.aimAxis = enumAttr.create("aimAxis", "aa", 0) enumAttr.addField("X", 0) enumAttr.addField("Y", 1) enumAttr.addField("Z", 2) enumAttr.addField("-X", 3) enumAttr.addField("-Y", 4) enumAttr.addField("-Z", 5) enumAttr.keyable = False cls.addAttribute(cls.aimAxis) cls.upAxis = enumAttr.create("upAxis", "ua", 2) enumAttr.addField("X", 0) enumAttr.addField("Y", 1) enumAttr.addField("Z", 2) enumAttr.addField("-X", 3) enumAttr.addField("-Y", 4) enumAttr.addField("-Z", 5) enumAttr.keyable = False cls.addAttribute(cls.upAxis) cls.aimVector = nAttr.create("aimVector", "av", OpenMaya.MFnNumericData.k3Double) cls.addAttribute(cls.aimVector) cls.upVector = nAttr.create("upVector", "uv", OpenMaya.MFnNumericData.k3Double) cls.addAttribute(cls.upVector) cls.provideAimVector = nAttr.create("provideAimVector", "pav", OpenMaya.MFnNumericData.kBoolean, 0) cls.addAttribute(cls.provideAimVector) cls.baseMatrix = matrixAttr.create("baseMatrix", "base", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.baseMatrix) cls.hingeMatrix = matrixAttr.create("hingeMatrix", "hng", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.hingeMatrix) cls.endMatrix = matrixAttr.create("endMatrix", "end", OpenMaya.MFnMatrixAttribute.kDouble) cls.addAttribute(cls.endMatrix) cls.useChildBaseAsEnd = nAttr.create("useChildBaseAsEnd", "ucb", OpenMaya.MFnNumericData.kBoolean, 0) cls.addAttribute(cls.useChildBaseAsEnd) cls.handle = messageAttr.create("handle", "hndl") messageAttr.array = True cls.addAttribute(cls.handle) cls.handleColor = nAttr.createColor("handleColor", "hc") cls.addAttribute(cls.handleColor) cls.orientGroup = messageAttr.create("orientGroup", "ogrp") cls.addAttribute(cls.orientGroup) cls.orientGroupTranslateX = uAttr.create("orientGroupTranslateX", "ogtx", OpenMaya.MFnUnitAttribute.kDistance, 0.0) cls.orientGroupTranslateY = uAttr.create("orientGroupTranslateY", "ogty", OpenMaya.MFnUnitAttribute.kDistance, 0.0) cls.orientGroupTranslateZ = uAttr.create("orientGroupTranslateZ", "ogtz", OpenMaya.MFnUnitAttribute.kDistance, 0.0) cls.orientGroupTranslate = nAttr.create("orientGroupTranslate", "ogt", cls.orientGroupTranslateX, cls.orientGroupTranslateY, cls.orientGroupTranslateZ) cls.addAttribute(cls.orientGroupTranslate) cls.orientGroupRotateX = uAttr.create("orientGroupRotateX", "ogrx", OpenMaya.MFnUnitAttribute.kAngle, 0.0) cls.orientGroupRotateY = uAttr.create("orientGroupRotateY", "ogry", OpenMaya.MFnUnitAttribute.kAngle, 0.0) cls.orientGroupRotateZ = uAttr.create("orientGroupRotateZ", "ogrz", OpenMaya.MFnUnitAttribute.kAngle, 0.0) cls.orientGroupRotate = nAttr.create("orientGroupRotate", "ogr", cls.orientGroupRotateX, cls.orientGroupRotateY, cls.orientGroupRotateZ) cls.addAttribute(cls.orientGroupRotate) cls.parentGuide = messageAttr.create("parentGuide", "pg") cls.addAttribute(cls.parentGuide) cls.parentGuideHandleIndex = nAttr.create("parentGuideHandleIndex", "pghi", OpenMaya.MFnNumericData.kShort, -1) cls.addAttribute(cls.parentGuideHandleIndex) cls.childGuide = messageAttr.create("childGuide", "cg") cls.addAttribute(cls.childGuide) cls.attributeAffects(cls.guideMatrix, cls.boundingBoxCorner1) cls.attributeAffects(cls.guideMatrix, cls.boundingBoxCorner2) # cls.attributeAffects(cls.baseMatrix, cls.boundingBoxCorner1) # cls.attributeAffects(cls.baseMatrix, cls.boundingBoxCorner2) cls.attributeAffects(cls.baseMatrix, cls.orientGroupTranslate) cls.attributeAffects(cls.baseMatrix, cls.orientGroupRotate) cls.attributeAffects(cls.baseMatrix, cls.aimVector) cls.attributeAffects(cls.baseMatrix, cls.upVector) # cls.attributeAffects(cls.hingeMatrix, cls.boundingBoxCorner1) # cls.attributeAffects(cls.hingeMatrix, cls.boundingBoxCorner2) cls.attributeAffects(cls.hingeMatrix, cls.orientGroupTranslate) cls.attributeAffects(cls.hingeMatrix, cls.orientGroupRotate) cls.attributeAffects(cls.hingeMatrix, cls.aimVector) cls.attributeAffects(cls.hingeMatrix, cls.upVector) # cls.attributeAffects(cls.endMatrix, cls.boundingBoxCorner1) # cls.attributeAffects(cls.endMatrix, cls.boundingBoxCorner2) cls.attributeAffects(cls.endMatrix, cls.orientGroupTranslate) cls.attributeAffects(cls.endMatrix, cls.orientGroupRotate) cls.attributeAffects(cls.endMatrix, cls.aimVector) cls.attributeAffects(cls.endMatrix, cls.upVector) cls.attributeAffects(cls.guideMatrix, cls.handleInverseScale) cls.attributeAffects(cls.provideAimVector, cls.aimVector)