def multiply(self, *args): """ Returns the Nodex for the sumMatrix attribute for this matrix multiplied with the other arguments Uses the `multMatrix` node from the `matrixNodes` plug-in in Maya. :type *args: :class:`nodex.datatypes.Matrix` :rtype: :class:`nodex.datatypes.Matrix` """ nodex.utils.ensurePluginsLoaded(self._plugins) # ensure arguments are Nodex args = tuple(Nodex(x) if not isinstance(x, Nodex) else x for x in args) # ensure all Nodex are Matrix for x in args: if not isinstance(x, Matrix): raise TypeError( "Provided arguments must be of type 'nodex.datatypes.Matrix', " "instead got {0}".format(x)) n = pymel.core.createNode("multMatrix") self.connect(n.attr("matrixIn[0]")) for i, other_input_arg in enumerate(args): other_input_arg.connect(n.attr("matrixIn[{0}]".format(i + 1))) return Nodex(n.attr("matrixSum"))
def _vectorProduct(input1=None, input2=None, matrix=None, operation=None, normalizeOutput=None, **kwargs): name = kwargs.get('name', 'vectorProduct') n = pymel.core.createNode("vectorProduct", name=name) if operation is not None: n.attr('operation').set(operation) if input1 is not None: Nodex(input1).connect(n.attr('input1')) if input2 is not None: Nodex(input2).connect(n.attr('input2')) if matrix is not None: # used for operations: Vector Matrix Product and Point Matrix Product Nodex(matrix).connect(n.attr('matrix')) if normalizeOutput is not None and normalizeOutput is not False: Nodex(normalizeOutput).connect(n.attr('normalizeOutput')) return Nodex(n.attr('output'))
def _distanceBetween(point1=None, point2=None, **kwargs): name = kwargs.get('name', 'distanceBetween') n = pymel.core.createNode("distanceBetween", name=name) if point1 is not None: Nodex(point1).connect(n.attr('point1')) if point2 is not None: Nodex(point2).connect(n.attr('point2')) return Nodex(n.attr('distance'))
def compose(cls, translate=(0, 0, 0), rotate=(0, 0, 0), scale=(1, 1, 1), shear=(0, 0, 0)): nodex.utils.ensurePluginsLoaded(cls._plugins) composeNode = pymel.core.createNode("composeMatrix") if translate != (0, 0, 0): Nodex(translate).connect(composeNode.attr('inputTranslate')) if rotate != (0, 0, 0): Nodex(rotate).connect(composeNode.attr('inputRotate')) if scale != (1, 1, 1): Nodex(scale).connect(composeNode.attr('inputScale')) if shear != (0, 0, 0): Nodex(shear).connect(composeNode.attr('inputShear')) return Nodex(composeNode.attr('outputMatrix'))
def hold(self): """ Cache a matrix. Uses the `holdMatrix` node built-in from Maya. :rtype: :class:`nodex.datatypes.Matrix` """ n = pymel.core.createNode("holdMatrix") self.connect(n.attr("inMatrix")) return Nodex(n.attr("outMatrix"))
def passMatrix(self, scale=None): """ Multiply a matrix by a constant without caching anything .. note:: 'pass' shadows a built-in of Python, therefore this method is named 'passMatrix' :param scale: Scale factor on input matrix :return: The 'outMatrix' attribute as Nodex :rtype: :class:`nodex.datatypes.Matrix` """ # no plug-in required (tested maya 2015) # nodex.utils.ensurePluginsLoaded(self._plugins) n = pymel.core.createNode("passMatrix") self.connect(n.attr("inMatrix")) if scale is not None: Nodex(scale).connect(n.attr("inScale")) return Nodex(n.attr("outMatrix"))
def transpose(self): """ Returns the Nodex for the outputMatrix attribute for the transpose of this Matrix Uses the `transposeMatrix` node from the `matrixNodes` plug-in in Maya. :rtype: :class:`nodex.datatypes.Matrix` """ nodex.utils.ensurePluginsLoaded(self._plugins) n = pymel.core.createNode("transposeMatrix") self.connect(n.attr("inputMatrix")) return Nodex(n.attr("outputMatrix"))
def decompose(self, translate=None, rotate=None, scale=None, shear=None, quat=None, chainAttr="outputTranslate"): """ Decomposes a Matrix into its translate, rotate (euler and quat), scale, shear values. :rtype: :class:`nodex.datatypes.Vector` """ nodex.utils.ensurePluginsLoaded(self._plugins) decomposeNode = pymel.core.createNode("decomposeMatrix") self.connect(decomposeNode.attr("inputMatrix")) if translate is not None: Nodex(decomposeNode.attr("outputTranslate")).connect(translate) if rotate is not None: Nodex(decomposeNode.attr("outputRotate")).connect(rotate) if scale is not None: Nodex(decomposeNode.attr("outputScale")).connect(scale) if shear is not None: Nodex(decomposeNode.attr("outputShear")).connect(shear) if quat is not None: Nodex(decomposeNode.attr("outputQuat")).connect(quat) # Assume chain output based on chainAttr return Nodex(decomposeNode.attr(chainAttr))
def _angleBetween(vector1=None, vector2=None, angle=None, axis=None, euler=None, chainAttr='angle', **kwargs): name = kwargs.get('name', 'angleBetween') n = pymel.core.createNode("angleBetween", name=name) # inputs if vector1 is not None: Nodex(vector1).connect(n.attr('vector1')) if vector2 is not None: Nodex(vector2).connect(n.attr('vector2')) # outputs if angle is not None: Nodex(n.attr('angle')).connect(angle) if axis is not None: Nodex(n.attr('axisAngle.axis')).connect(axis) if euler is not None: Nodex(n.attr('euler')).connect(euler) return Nodex(n.attr(chainAttr))
def dot(self, other, normalizeOutput=False): """ Returns the dot product of this and another `Vector`. :param other: The other vector :type other: :class:`nodex.datatypes.Vector` :param normalizeOutput: If True normalizes the output Vector. :type normalizeOutput: :class:`nodex.datatypes.Float` :return: The dot product :rtype: :class:`nodex.datatypes.Vector` """ output = self._vectorProduct(self, other, operation=1, normalizeOutput=normalizeOutput, name="vectorDot") # The dot product only results in one value, so get the outputX return Nodex(output.node().attr('outputX'))
def convertData(self, data): if isinstance(data, pymel.core.Attribute): return data elif isinstance(data, basestring): return pymel.core.Attribute(data) if isinstance(data, (tuple, list)): # Convert any references internal to the array data = tuple(Nodex(x) for x in data) # Validate every element has max single dimension of depth if any(x.dimensions() > 1 for x in data): raise ValueError( "Can't create an Array type of Nodex that nests attributes/values with a " "higher dimension than one.") return data raise TypeError()
def isValidData(data): # attribute if isinstance(data, pymel.core.Attribute): return Array.validateAttr(data) elif isinstance(data, basestring): try: attr = pymel.core.Attribute(data) return Array.validateAttr(attr) except RuntimeError: return False # list elif isinstance(data, (list, tuple)): if len(data) == 0: return False # This is relatively slow... but hey, let's keep it for now (should be mergeable with below) if any(Nodex(x).dimensions() > 1 for x in data): return False return True return False