def test_dagPathVSMobjects( self ): node = nt.createNode( "parent|middle|child", "transform" ) nodem = nt.Node( "parent|middle" ) duplnodemiddle = nodem.duplicate( "middle1" ) instnode = duplnodemiddle.addInstancedChild( node ) assert instnode.object() == node.object() # compare mobject assert instnode != node # compare dag paths path = instnode.dagPath( ) childm1 = nt.Node( "parent|middle1|child" ) # if it didnt work, he would have returned a "|parent|middle|child" assert "|parent|middle1|child" == str(childm1) npath = node.dagPath( ) ipath = instnode.dagPath( ) assert npath != ipath assert node.object() == instnode.object() # same object after all # if an MObject is passed in, it should still work assert node == instnode.object() # using an attribute would create a DagNode which corresponds to the first path assert not node != instnode.wm.mwrappedNode() assert node == instnode.wm.mwrappedNode()
def test_instancesAndParenting( self ): mrvmaya.Scene.open( get_maya_file( "instancetest.ma" ), force=True ) m = nt.Node( "m" ) # mesh, two direct and two indirect instances c1 = nt.createNode( "|c1", "transform" ) assert m.instanceCount( 0 ) == 2 assert m.instanceCount( 1 ) == 4 # test parenting mci = c1.addInstancedChild( m ) assert m.instanceCount( 0 ) == 3 assert m.instanceCount( 1 ) == 5 # direct + indirect c1.removeChild( mci ) assert m.instanceCount( 0 ) == 2 assert m.instanceCount( 1 ) == 4 # direct + indirect # check reparent d1 = nt.createNode( "|d1", "transform" ) c1 = c1.reparent( d1 ) assert m.instanceCount( 0 ) == 2 assert m.instanceCount( 1 ) == 4 # reparent an instanced transform under d1 a2 = nt.Node( "a2" ) a2 = a2.reparent( d1, raiseOnInstance=0 ) # destroys instances assert m.instanceCount( 0 ) == 2 assert m.instanceCount( 1 ) == 2
def test_anim_overrides(self): # create test anim curve p = nt.Node('persp') anim_curve = nt.anim.apianim.MFnAnimCurve().create(p.rx) assert isinstance(anim_curve, nt.api.MObject) # test mfn wrapping anim_curve = nt.Node(anim_curve) assert anim_curve.numKeyframes() == 0 # assure we are connected to the plug, for curiousity assert p.rx in anim_curve.output.moutputs() assert p.ry not in anim_curve.output.moutputs() # set key anim_curve.setIsWeighted(True) anim_curve.addKeyframe(nt.api.MTime(-1.0), 5.0) anim_curve.addKeyframe(nt.api.MTime(1.0), 10.0) assert anim_curve.numKeyframes() == 2 # test method overrides for index in range(anim_curve.numKeyframes()): for isInTangent in range(2): rval = anim_curve.getTangent(index, isInTangent) assert isinstance(rval, tuple) and len(rval) == 2 assert rval[0] != 0.0 and rval[1] != 0.0 rval = anim_curve.getTangentAsAngle(index, isInTangent) assert len(rval) == 2 assert isinstance(rval[0], api.MAngle) assert rval[0].value() != 0.0 and rval[1] != 0.0
def _getMemberList(self): """:return: object list with all types""" persp = nt.Node("persp") front = nt.Node("front") rg = nt.Node("defaultRenderGlobals") ik = nt.Node("ikSystem") s2 = nt.Node("defaultObjectSet") return [ik, persp, persp.translate, rg.object(), front.dagPath(), s2]
def test_lightLinkCopy(self): # currently we only call variants of the respective method to run it - verification # was made in actual scenes, but they were not incorporated into the test.""" for sourcename in ("sphere", "torus"): source = nt.Node(sourcename) target = nt.Node("%s_target" % sourcename) source.copyLightLinks(target, substitute=1) # substitute to target target.copyLightLinks(source, substitute=1) # back to source source.copyLightLinks(target, substitute=0) # copy it to target
def test_z_memberHandlingComps(self): p1 = nt.Node("|p1trans|p1") s1 = nt.Node("s1") # sphere with face shader assignments s2 = nt.Node("s2") # sphere with one object assignment # shading engines sg1 = nt.Node("sg1") sg2 = nt.Node("sg2") # REMOVE AND SET FACE ASSIGNMENTS #################################### # get all sets assignments setcomps = p1.componentAssignments(setFilter=nt.Shape.fSetsRenderable) for setnode, comp in setcomps: # NOTE: must be member in the beginning, but the isMember method does not # work properly with components if comp.isNull(): continue assert setnode.isMember(p1, component=comp) # remove the components p1.removeFrom(setnode, component=comp) assert not setnode.isMember(p1, component=comp) # add member again setnode.addMember(p1, component=comp, ignore_failure=False) assert setnode.isMember(p1, component=comp) # END for each set component assignment # create a component with 3 faces f3 = nt.SingleIndexedComponent.create(api.MFn.kMeshPolygonComponent) for i in range(3): f3.addElement(i) f6 = nt.SingleIndexedComponent.create(api.MFn.kMeshPolygonComponent) for i in range(3, 6): f6.addElement(i) # FORCE OVERWRITING EXISITNG FACE ASSIGNMNETS ############################################### for sg, comp in zip((sg1, sg2), (f3, f6)): self.failUnlessRaises(nt.ConstraintError, sg.addMember, s1, component=f3) # force it s1.addTo(sg, component=comp, force=1) assert s1.isMemberOf(sg, component=comp)
def test_tranformation_overrides(self): p = nt.Node('persp') getters = ('getScale', 'getShear') setters = ('setScale', 'setShear') def cmp_val(lhs, rhs, loose): if loose: assert lhs != rhs else: assert lhs == rhs # END util def assert_values(fgetname, fsetname, loose): getter = getattr(p, fgetname) v = getter() assert isinstance(v, api.MVector) nv = api.MVector(i+v.x+1.0, i+v.y+2.0, i+v.z+3.0) getattr(p, fsetname)(nv) cmp_val(nv, getter(), loose) cmds.undo() cmp_val(v, getter(), loose) cmds.redo() cmp_val(nv, getter(), loose) # END utility for i,(fgetname, fsetname) in enumerate(zip(getters, setters)): assert_values(fgetname, fsetname, loose=False) # END for each fname setters = ("scaleBy", "shearBy") for i,(fgetname, fsetname) in enumerate(zip(getters, setters)): assert_values(fgetname, fsetname, loose=True)
def test_add_and_retrieve_complex_datatype_using_mrv(self): p = nt.Node("persp") p.addAttribute( nt.TypedAttribute.create('stringarray', 'sa', Data.Type.kStringArray, nt.StringArrayData.create())) p.sa.masData().array()
def test_shader_comonent_assignments(self): # MESH COMPONENTS ################# isb = nt.Node("initialShadingGroup") m = nt.Mesh() pc = nt.PolyCube() pc.output.mconnectTo(m.inMesh) assert len(m.componentAssignments()) == 0 and m.numVertices() == 8 # assign two of the 6 faces isb.addMember(m, m.cf[2, 4]) asm = m.componentAssignments() assert len(asm) == 1 asm = asm[0] assert asm[0] == isb and len(asm[1].elements()) == 2 # verify return types of getComponentAssignments asm = m.componentAssignments(asComponent=False) assert not isinstance(asm[0][1], nt.Component) # assign everything on component level isb.addMember(m, m.cf[:]) asm = m.componentAssignments() assert len(asm) == 1 asm = asm[0] # IMPORTANT: Setting the component complete doesnt work - it will just # do nothing as it doesnt check for that assert not asm[1].isComplete( ) # it should be complete, but maya doesnt think so # assign all 6 faces isb.addMember(m, m.cf[:6]) asm = m.componentAssignments() assert len(asm) == 1 asm = asm[0] assert len(asm[1].elements()) == 6 # unassign by assigning other faces does NOT work isb.addMember(m, m.cf[:3]) assert len(m.componentAssignments()[0][1].elements()) == 6 # unassign all components at once does work ! isb.removeMember(m, m.cf[:]) asm = m.componentAssignments() assert len(asm) == 0 # unassign just a few of many faces isb.addMember(m, m.cf[:6]) assert len(m.componentAssignments()) == 1 isb.removeMember(m, m.cf[:5]) asm = m.componentAssignments()[0] e = asm[1].elements() assert len(e) == 1 and e[0] == 5 # test object level assignments vs. component assignments # Although they should be exclusive, they are not, hence component level # assignments stay, the object level ones take precedence isb.addMember(m) assert len(m.componentAssignments()) == 1 assert m in isb
def test_set_assignments(self): m = nt.Node('mesh40k') isb = nt.ShadingEngine() for ignore_failure in range(2): if ignore_failure > 0: isb.removeMember(m, m.cf[:]) # END initial assignment clearing # IntArray np = m.numPolygons() st = time.time() isb.addMember(m, m.cf[:np], ignore_failure=ignore_failure) elapsed = time.time() - st print >> sys.stderr, "Assigned %i polygons (IntArray, ignore_failure=%i) in %f s ( %f polys/s )" % ( np, ignore_failure, elapsed, np / elapsed) # remove with complete data st = time.time() isb.removeMember(m, m.cf[:]) elapsed = time.time() - st print >> sys.stderr, "Unassigned %i polygons (setComplete) in %f s ( %f polys/s )" % ( np, elapsed, np / elapsed) # with complete data st = time.time() c = m.cf.empty() c.setCompleteData(np) isb.addMember(m, c, ignore_failure=ignore_failure) elapsed = time.time() - st print >> sys.stderr, "Assigned %i polygons (setCompleteData, ignore_failure=%i) in %f s ( %f polys/s )" % ( np, ignore_failure, elapsed, np / elapsed)
def test_hashfunc( self ): """byroimo.maya.nt: should be possible to use objects as keys in hashes""" # they must compare their objects for equality, not their own instance ddg = dict() for i in range( 10 ): # dg nodes ddg[ nt.Node( "initialShadingGroup" ) ] = i assert len( ddg ) == 1 ddag = dict() for i in range( 10 ): # dg nodes ddag[ nt.Node( "persp" ) ] = i assert len( ddag ) == 1 # merge both together dall = dict() dall.update( ddg ) dall.update( ddag ) assert len( dall ) == 2
def test_convenienceFunctions( self ): # SELECTION ############ nt.select( "persp" ) persp = nt.selection()[0] assert persp == nt.Node( "persp" ) # clear selection nt.select( ) assert not nt.selection() # undo/redo cmds.undo() assert len(nt.selection()) == 1 cmds.redo() assert len(nt.selection()) == 0 # select object and selection list nt.select( persp ) assert len( nt.selection( ) ) == 1 nt.select( nt.toSelectionList( nt.selection( ) ) ) assert len( nt.selection( ) ) == 1 # select mixed nt.select( persp, "front" ) assert len( nt.selection( ) ) == 2 # GET BY NAME ############### persp = nt.findByName( "pers*" )[0] assert persp == nt.Node( "persp" ) # filter selection ################## nt.select("persp", "perspShape") assert len(nt.selection(api.MFn.kCamera)) == 1 assert len(list(nt.iterSelection(api.MFn.kCamera))) == 1 sl = nt.activeSelectionList() assert len(sl) and isinstance(sl, api.MSelectionList)
def post_standalone_initialized(self): # plugin shouldn't have loaded import maya.cmds as cmds import mrv.maya undo_plugin_file = os.path.splitext(mrv.maya.undo.__file__)[0] + '.py' assert not cmds.pluginInfo( undo_plugin_file, q=1, loaded=1 ) # should still be able to use MPlug.msetX import mrv.maya.nt as nt p = nt.Node("persp") p.tx.msetDouble(10.0) assert p.tx.asDouble() == 10.0
def setupScene(cls, ptexture_name): """Open the given ptexture scene and set it up :return: tuple(ptexnode, mesh) tuple of ptex node and the connected mesh shape""" base = fixture_path(ptexture_name) cls.openScene(base / 'scene.ma') m = nt.Node("meshShape") assert (isinstance(m, nt.Mesh)) n = cls.makeNode("PtexVisNode") m.outMesh.mconnectTo(n.inMesh) n.ptfp.setString(str(cls.ptexturePath(ptexture_name))) return n, m
def test_plug_itertools(self): p = nt.Node('persp') p.tx.mconnectTo(p.ty).mconnectTo(p.tz) # check future pxf = list(p.tx.miterOutputGraph()) assert len(pxf) == 3 assert pxf[0] == p.tx and pxf[1] == p.ty and pxf[2] == p.tz # check history pzh = list(p.tz.miterInputGraph()) assert len(pzh) == 3 assert pzh[0] == p.tz and pzh[1] == p.ty and pzh[2] == p.tx
def test_set_vertex_colors(self): st = time.time() cset = 'edgeLength' m = nt.Node('mesh40k') m.createColorSetWithName(cset) m.setCurrentColorSetName(cset) lp = nt.api.MPointArray() m.getPoints(lp) colors = nt.api.MColorArray() colors.setLength(m.numVertices()) vids = nt.api.MIntArray() vids.setLength(len(colors)) el = nt.api.MFloatArray() el.setLength(len(colors)) cvids = nt.api.MIntArray() # compute average edge-lengths max_len = 0.0 for vid, vit in enumerate(m.vtx): vit.getConnectedVertices(cvids) cvp = lp[vid] accum_edge_len=0.0 for cvid in cvids: accum_edge_len += (lp[cvid] - cvp).length() # END for each edge-id avg_len = accum_edge_len / len(cvids) max_len = max(avg_len, max_len) el[vid] = avg_len vids[vid] = vid # END for each vertex # normalize for cid in xrange(len(colors)): c = colors[cid] c.b = el[cid] / max_len colors[cid] = c # END for each color id m.setVertexColors(colors, vids, nt.api.MDGModifier()) elapsed = time.time() - st nc = len(colors) print >>sys.stderr, "Computed %i vertex colors ans assigned them in %f s ( %f colors/s )" % (nc, elapsed, nc/elapsed)
def test_reparentAndInstances( self ): mesh = nt.createNode( "trans|mesh", "mesh" ) base = nt.createNode( "base|subbase", "transform" ) obase = nt.createNode( "obase|subbase2", "transform" ) rbase = nt.createNode( "reparentBase", "transform" ) # test basic functions assert rbase.apiType() == api.MFn.kTransform assert rbase.hasFn( api.MFn.kTransform ) baseinst = base.addInstancedChild( mesh ) obaseinst = obase.addInstancedChild( mesh ) # try to re-wrap the instanced items assert nt.Node( str( baseinst ) ) == baseinst assert nt.Node( str( obaseinst ) ) == obaseinst # use partial name assert nt.Node( "subbase|mesh" ) == baseinst assert nt.Node( "subbase2|mesh" ) == obaseinst assert mesh.isValid() and baseinst.isValid() and obaseinst.isValid() # assure we catch this possibly damaage self.failUnlessRaises( RuntimeError, mesh.reparent, rbase, raiseOnInstance=True ) # instances are gone should be gone mesh = mesh.reparent( rbase, raiseOnInstance=False ) assert mesh.isValid() and not baseinst.isValid() and not obaseinst.isValid() # try unparent meshtrans = mesh.transform() meshtrans.setParent(obase) assert meshtrans.parent() == obase meshtrans.unparent() assert meshtrans.parent() is None
def test_graph_iteration(self): root = nt.Node('Jetctrllers') for rootitem in (root, root.drawInfo): for breadth in range(2): for plug in range(2): for asNode in range(2): st = time.time( ) ic = 0 for item in it.iterGraph(rootitem, breadth=breadth, plug=plug, asNode=asNode): ic += 1 # END for each item elapsed = time.time() - st if elapsed == 0.0: elapsed = 0.001 # END handle very small values ( or unprecise timers on windows ) print >>sys.stderr, "iterGraph: Traversed %i items from %s (asNode=%i, plug=%i, breadth=%i) in %f s ( %f / s )" % ( ic, rootitem, asNode, plug, breadth, elapsed, ic / elapsed )
def test_storageAttributeHanlding( self ): mrvmaya.Scene.new( force = True ) snode = nt.createNode( "storage", "storageNode" ) # autocreate off self.failUnlessRaises( AttributeError, snode.pythonData, "test" ) data = snode.dta val = snode.pythonData( "test", autoCreate=True ) oval = snode.pythonData( "othertest", autoCreate=True ) assert len( data ) == 2 # have two right now, no prefix assert len( snode.dataIDs() ) == 2 # CLEAR EMPTY DATA ###################### snode.clearData( "test" ) # PREFIXES ############ snode._attrprefix = "prefix" # must create new one pval = snode.pythonData( "othertest", autoCreate=True ) assert len( data ) == 3 assert pval._plug.mparent().mchildByName('id').asString() == "prefixothertest" # now that we have a prefix, we only see prefixed attributes assert len( snode.dataIDs() ) == 1 # STORAGE PLUGS ( MAIN PLUG ) # contains connection plug too mainplug = snode.findStoragePlug( "othertest" ) assert mainplug == pval._plug.mparent() # CONNECTION PLUGS ################### persp = nt.Node( "persp" ) conarray = mainplug.mchildByName('dmsg') for c in range( 10 ): nextplug = conarray.elementByLogicalIndex( c ) persp.message.mconnectTo(nextplug) assert persp.message.misConnectedTo(nextplug) assert len( conarray ) == 10 assert len( persp.message.moutputs() ) == 10
def test_matrixData(self): node = nt.Node("persp") matplug = node.findPlug("worldMatrix") assert not matplug.isNull() assert matplug.isArray() matplug.evaluateNumElements() # to assure we have something ! assert matplug.name() == "persp.worldMatrix" assert len(matplug) matelm = matplug[0] assert matelm == matplug.elementByLogicalIndex( 0) # get by logical index assert not matelm.isNull() matdata = matelm.masData() assert isinstance(matdata, nt.MatrixData) mmatrix = matdata.matrix() assert isinstance(mmatrix, api.MMatrix)
def test_typeconversion_overhead(self): # this method will be extended once we actually do typeconversions automatically ps = nt.Node("perspShape") n = 10000 # if this check fails, the test needs to be updated, as we now obviously # implement typeconversions self.failUnlessRaises(TypeError, ps.hasSamePerspective, ps) # use api method here to get the pure marshalling overhead hasSamePerspective = ps._api_hasSamePerspective # OPTIMAL CONVERSION # we know that we have to convert st = time.time() for i in xrange(n): hasSamePerspective(ps.dagPath()) # END for each iteration elapsedotc = time.time() - st # NORMAL CONVERSION # the type has to be checked st = time.time() for i in xrange(n): if type(ps) is not api.MDagPath: hasSamePerspective(ps.dagPath()) else: hasSamePerspective(ps) # never gets called # END for each iteration elapseddtc = time.time() - st # WITHOUT CONVERSION # the proper type is passed in right away st = time.time() psdp = ps.dagPath() for i in xrange(n): hasSamePerspective(psdp) # END for each iteration elapsedntc = time.time() - st print >>sys.stderr, "Called MFnMethod %i times without (%f s, %f calls / s), with optimal (%f s) and with normal type conversion(%f s), overhead is 1.0~%f~%f" % (n, elapsedntc, n/elapsedntc, elapsedotc, elapseddtc, elapsedotc/elapsedntc, elapseddtc/elapsedntc)
def test_wrapping(self): # from string p = nt.Node("persp") # it tries to access it like an APIObj - no type checks done here self.failUnlessRaises(AttributeError, nt.NodeFromObj, "persp") # we don't accept other Nodes - it makes no sense and should be fixed self.failUnlessRaises(TypeError, nt.Node, p) # works, but first mfn access fails ! pfail = nt.NodeFromObj(p) # oh look, how inconsistent the wrap is :) ... try: pfail.findPlug('wm') except (RuntimeError, TypeError, NotImplementedError): # yes, it actually throws all kinds of different exceptions # depending on the OS and the maya version pass else: self.fail("Expected exception")
def test_get_animation(self): mmaya.Scene.new(force=True) p = nt.Node("persp") # translate is animated for tc in p.translate.mchildren(): apianim.MFnAnimCurve().create(tc) # END set animation # test animation iteration for converter in (lambda x: x, lambda x: nt.toSelectionList(x)): for as_node in range(2): nc = 0 target_type = nt.api.MObject if as_node: target_type = nt.Node # END define target type for anode in nt.AnimCurve.findAnimation( converter([p]), as_node): assert isinstance(anode, target_type) nc += 1 # END for each anim node assert nc == 3
def test_MPlugArray(self): node = nt.Node("defaultRenderGlobals") pa = node.connections() myplug = pa[0] myplug.name( ) # special Plug method not available in the pure api object pa.append(myplug) assert len(pa) == 4 # SETITEM l = 5 pa.setLength(l) nullplug = pa[0] for i in range(l): pa[i] = nullplug # __ITER__ for plug in pa: plug.name() assert isinstance(plug, api.MPlug) self.failIf(len(pa) != 5)
def test_mesh_iteration(self): m = nt.Node('mesh40k') nv = m.numVertices() ne = m.numEdges() nf = m.numPolygons() # VTX NOOP st = time.time() nc = 0 for it in m.vtx: nc += 1 # to be sure it doesnt get optimized, which doesnt happen actually # END for each vertex assert nc == nv noop_elapsed = time.time() - st print >>sys.stderr, "Iterated %i vertices and noop in %f s ( %f items/s )" % (nv, noop_elapsed, nv/noop_elapsed) # VTX INDEX st = time.time() for it in m.vtx: it.index() # END for each vertex index_elapsed = time.time() - st print >>sys.stderr, "Iterated %i vertices and queried index in %f s ( %f indices/s )" % (nv, index_elapsed, nv/index_elapsed) # VTX INDEX st = time.time() vit = m.iterComponents(m.eComponentType.vertex) vitindex = vit.index for it in vit: vitindex() # END for each vertex indexc_elapsed = time.time() - st print >>sys.stderr, "Iterated %i vertices and queried index (cached) in %f s ( %f indices/s )" % (nv, indexc_elapsed, nv/indexc_elapsed) print >>sys.stderr, "Call-overhead estimation: noop (%f) vs. index(%f)=^%f vs cached index(%f)=^%f" % ( noop_elapsed, index_elapsed, index_elapsed/noop_elapsed, indexc_elapsed, indexc_elapsed/noop_elapsed ) # VTX POSITION st = time.time() for it in m.vtx: it.position() # END for each vertex elapsed = time.time() - st print >>sys.stderr, "Iterated %i vertices and queried position in %f s ( %f pos/s )" % (nv, elapsed, nv/elapsed) # EDGE 2 POSITION st = time.time() for it in m.e: it.point(0) it.point(1) # END for each vertex elapsed = time.time() - st print >>sys.stderr, "Iterated %i edges and queried position in %f s ( %f pos/s )" % (ne, elapsed, nv/elapsed) # Polygon All vtx st = time.time() ia = nt.api.MIntArray() nc = 0 for it in m.f: it.getVertices(ia) nc += 1 # END for each vertex assert nc == nf elapsed = time.time() - st print >>sys.stderr, "Iterated %i polygons and queried all poly-vertices in %f s ( %f queries/s )" % (nf, elapsed, nv/elapsed) # All FaceVtx st = time.time() nc = 0 for it in m.map: it.position() nc += 1 # END for each vertex elapsed = time.time() - st print >>sys.stderr, "Iterated %i face-vertices and queried position in %f s ( %f queries/s )" % (nc, elapsed, nc/elapsed)
def test_replacing_default_node_types(self): n = nt.Network() sn = StorageNetworkNode.create() # REPLACING BUILTIN NODE TYPES ############################## # if we want to play crazy, we can make all network nodes our special # storage node, be replacing the existing Network node type. # Any instantiation will fail as if its not one of our specialized nodes, # but this is implementation defined of course. # Defining a new derived Type automatically puts it into the nt module OldNetwork = nt.Network class Network(StorageNetworkNode): def sayhello(self): print "hello" # yes, the official Network node is now our own one, automatically assert nt.Network is Network sn2 = nt.Node(str(sn)) assert isinstance(sn2, StorageNetworkNode) assert isinstance(sn2.dataIDs(), list) # and it can say something sn2.sayhello() # we cannot wrap normal nodes as our initializer on StorageNetworkNode barks # if the vital data plug cannot be found. self.failUnlessRaises(TypeError, nt.Node, str(n)) # reset the old one, we affect everything within MRV now nt.removeCustomType(Network) nt.addCustomType(OldNetwork) # everything back to normal - we get plain old network nodes sn_network = nt.Node(sn.object()) assert type(sn_network) is OldNetwork assert type(sn_network) is nt.Network # REPLACING BUILTIN NODES PROPERLY ################################## class Network(OldNetwork, nt.StorageBase): def __init__(self, node): """Implement the initializer such that we only initialize our base if we have the 'data' attribute. Otherwise we keep it uninitialized, so it will not be functional""" try: super(Network, self).__init__(node) except TypeError: pass # END handle input type def sayaloha(self): print "aloha" # END better Super-Network implementation assert nt.Network is Network # now plain network nodes will be new Network nodes, but we are allowed # to create them # NodeFromObj works as well, just to be sure n2 = nt.NodeFromObj(n.object()) assert type(n2) is Network # as the storage base has not been initialized, we cannot do anything # with it. The actual point here though is that users who don't know the # interface will get a fully functional network node at least. # As we do not 'tighten' the interface, code that doesn't expect our type # will not get into trouble. self.failUnlessRaises(AttributeError, n2.dataIDs) assert isinstance(n2, OldNetwork) n2.sayaloha() # and storage network nodes will be 'Network' nodes whose additional # functions we can use sn2 = nt.Node(sn.object()) assert type(sn2) is Network sn2.sayaloha() sn2.dataIDs() # once again, get rid of our custom type, reset the old one nt.removeCustomType(Network) nt.addCustomType(OldNetwork) assert nt.Network is OldNetwork
def test_storagePickleData( self ): tmpdir = make_path( tempfile.gettempdir() ) def setTestValue( mydict ): mydict['string'] = "hello world" mydict[1] = 3.0 mydict["list"] = ["this", 2, 45.0] def checkTestValue( self, mydict ): sval = mydict.get( "string" ) assert sval == "hello world" fval = mydict.get( 1 ) assert fval == 3.0 lval = mydict.get( "list" ) assert len( lval ) == 3 def fix_ascii_file(filepath): """Unfortunately, on windows and osx and maya2011, ascii's tend to corrupt themselves by writing ',' into floats which should be a '.'. Could be something related to the locale too. Nonetheless, we have to fix it and do a stupid find a replace""" if filepath.ext() != '.ma': return tmpfile = make_path(tempfile.mktemp()) ofh = open(tmpfile, 'wb') for line in open(filepath): ofh.write(line.replace(',', '.')) # END for each line ofh.close() filepath.remove() tmpfile.move(filepath) did = "test" for filetype in [ ".ma", ".mb" ]: mrvmaya.Scene.new( force = True ) # BASIC DATA CREATION AND EDITING #################################### storagenode = nt.createNode( "storage", "storageNode" ) refcomparator = nt.createNode( "trans", "transform" ) pyval = storagenode.pythonData( did, autoCreate = True ) # adjust the value - will be changed in place setTestValue( pyval ) # SAVE AND LOAD ! ################# # ascii and binary ( including reference test ) filepath = tmpdir / ( "storagetest" + filetype ) mrvmaya.Scene.save( filepath ) fix_ascii_file(filepath) # reload mrvmaya.Scene.open( filepath, force=True ) # get and test data storagenode = nt.Node( "storage" ) pyvalloaded = storagenode.pythonData( did, autoCreate = False ) checkTestValue( self, pyvalloaded ) # CLEAR NON-EMPTY DATA WITH UNDO ################################## storagenode.clearData( did ) pydatacleared = storagenode.pythonData( did, autoCreate =False ) assert not pydatacleared.has_key( "string" ) cmds.undo() pydataundone = storagenode.pythonData( did, autoCreate =False ) assert pydataundone.has_key( "string" ) # CREATE REFERENCE ################## mrvmaya.Scene.new( force = True ) mrvmaya.ref.createReference( filepath, namespace="referenced" ) refstoragenode = nt.Node( "referenced:storage" ) refcomparator = nt.Node( "referenced:trans" ) pyval = refstoragenode.pythonData( did ) # adjust values pyval[ "refchange" ] = "changed in reference" refcomparator.tx.msetFloat( 5.5 ) # save reference filewithrefpath = tmpdir / ( "refstoragetest" + filetype ) mrvmaya.Scene.save( filewithrefpath ) fix_ascii_file(filewithrefpath) mrvmaya.Scene.open( filewithrefpath, force = True ) # check test value and the newly written one refstoragenode = nt.Node( "referenced:storage" ) pyval = refstoragenode.pythonData( did ) checkTestValue( self, pyval ) sval = pyval[ 'refchange' ] assert sval == "changed in reference" # DUPLICATION ############### for is_shallow in range( 2 ): duplicate = refstoragenode.duplicate( shallow = is_shallow ) ddata = duplicate.pythonData( did ) data = refstoragenode.pythonData( did ) checkTestValue( self, ddata ) # assure that its a real copy , not just something shallow if not is_shallow: data[ 'other' ] = 2 assert not ddata.has_key( 'other' )
def test_MSelectionList(self): sl = nt.toSelectionList(nt.it.iterDgNodes()) nodeset = set() # can be handled like a list assert len(sl) > 3 # provides unique wrapped nodes for node in sl.mtoIter(): assert isinstance(node, nt.Node) nodeset.add(node) # END for each node assert len(nodeset) == len(sl) # test creation functions node_list = list(sl.mtoIter()) nls = node_list[4:15] for slsnodesgen, selfun in ((lambda: [str(n) for n in nls], api.MSelectionList.mfromStrings), (lambda: nls, api.MSelectionList.mfromList), (lambda: [(n, api.MObject()) for n in node_list[-5:] if isinstance(n, nt.DagNode)], api.MSelectionList.mfromComponentList)): slsnodes = slsnodesgen() sls = selfun(iter(slsnodes)) assert isinstance(sls, api.MSelectionList) and len(sls) == len(slsnodes) # END for each variant # from multiple assert len(api.MSelectionList.mfromMultiple(*nls)) == len(nls) # from iter assert len(api.MSelectionList.mfromIter(iter(nls))) == len(nls) # test conversion methods assert list(sl.mtoIter()) == sl.mtoList() assert hasattr(sl.mtoIter(), 'next') # test contains dagnode = nt.Node("persp") dgnode = nt.Node("time1") plug = dgnode.o sls = api.MSelectionList.mfromList((dagnode, dgnode, plug)) assert len(sls) == 3 nc = 0 for item in sls.mtoIter(): assert sls.mhasItem(item) nc += 1 # END for each item assert nc == len(sls) # COMPONENT ITERATION m = nt.Mesh() nt.PolyCube().output > m.inMesh sl = api.MSelectionList() sl.add(m.dagPath()) sl.add(m.dagPath(), m.cf[:]) assert len(list(sl.miterComponents())) == 1 # PLUG ITERATION p = nt.Node("persp") sl = api.MSelectionList() sl.add(p.dagPath()) sl.add(p.t) sl.add(p.rx) assert len(list(sl.miterPlugs())) == 2
def test_MPlug(self): persp = nt.Node("persp") front = nt.Node("front") side = nt.Node("side") matworld = persp.worldMatrix assert isinstance(matworld.mfullyQualifiedName(), basestring) str(matworld) repr(matworld) # CONNECTIONS ####################### # CHECK COMPOUND ACCESS tx = persp.translate.mchildByName('tx') # can access attributes twice persp.translate # DO CONNECTIONS ( test undo/redo ) persp.translate.mconnectTo(front.translate, force=True) assert persp.translate.misConnectedTo( front.translate) # misConnectedTo assert persp.translate.minput().isNull() cmds.undo() assert not persp.translate.misConnectedTo(front.translate) cmds.redo() assert front.translate in persp.translate.moutputs() # check moutput assert persp.translate.moutput() == front.translate assert persp.rotate.moutput().isNull( ) # unconnected return nullPlus as minput does # CHECK CONNECTION FORCING persp.translate.mconnectTo(front.translate, force=False) # already connected self.failUnlessRaises(RuntimeError, persp.s.mconnectTo, front.translate, force=False) # overwrite connection side.translate.mconnectTo(front.translate) # force default True assert side.translate.misConnectedTo(front.translate) # undo - old connection should be back cmds.undo() assert persp.translate.misConnectedTo(front.translate) # disconnect input front.translate.mdisconnectInput() assert not persp.translate.misConnectedTo(front.translate) cmds.undo() # disconnect output persp.t.mdisconnectOutputs() assert len(persp.translate.moutputs()) == 0 cmds.undo() assert persp.t.misConnectedTo(front.translate) # disconnect from persp.t.mdisconnectFrom(front.translate) assert not persp.t.misConnectedTo(front.t) cmds.undo() assert persp.t.misConnectedTo(front.t) # COMPARISONS assert persp.t != front.t assert persp.t.mchildByName('tx') != persp.t.mchildByName('ty') # affected plugs affectedPlugs = persp.t.maffects() assert len(affectedPlugs) > 1 affectedPlugs = persp.t.maffected() assert len(affectedPlugs) > 1 # test multi connections sn = nt.createNode("network1", "network") sn2 = nt.createNode("network2", "network") tn = nt.createNode("network3", "network") def pir(array_plug, range_iter): for index in range_iter: yield array_plug.elementByLogicalIndex(index) # END for each item in range # END plugs-in-range # connect 10 to 10 r = range(10) api.MPlug.mconnectMultiToMulti(izip(pir(sn.a, r), pir(tn.affectedBy, r)), force=False) for i in r: assert sn.a.elementByLogicalIndex(i).misConnectedTo( tn.affectedBy.elementByLogicalIndex(i)) # END make connection assertion # connection of overlapping range fails without force r = range(5, 15) self.failUnlessRaises(RuntimeError, api.MPlug.mconnectMultiToMulti, izip(pir(sn2.a, r), pir(tn.affectedBy, r)), force=False) # there no connection should have worked ( its atomic ) # hence slot 10 is free persp.tx > tn.affectedBy.elementByLogicalIndex(10) # force connection works api.MPlug.mconnectMultiToMulti(izip(pir(sn2.a, r), pir(tn.affectedBy, r)), force=True) for i in r: assert sn2.a.elementByLogicalIndex(i).misConnectedTo( tn.affectedBy.elementByLogicalIndex(i)) # END make connection assertion # ATTRIBUTES AND UNDO ####################### funcs = (("isLocked", "msetLocked"), ("isKeyable", "msetKeyable"), ("isCachingFlagSet", "msetCaching"), ("isChannelBoxFlagSet", "msetChannelBox")) plugnames = ("t", "tx", "r", "rx", "s", "sy") for p in plugnames: plug = persp.findPlug(p) for (getname, setname) in funcs: fget = getattr(plug, getname) fset = getattr(plug, setname) curval = fget() oval = bool(1 - curval) fset(oval) # SPECIAL HANDLING as things cannot be uncached if setname == "msetCaching": continue assert fget() == oval cmds.undo() assert fget() == curval cmds.redo() assert fget() == oval fset(curval) # reset # END for each function # END for each plugname # QUERY ############################ # ELEMENT ITERATION matworld.evaluateNumElements() for elm in matworld: assert elm.mparent() == matworld translate = persp.translate assert len(translate.mchildren()) == translate.numChildren() # CHILD ITERATION for child in translate.mchildren(): assert child.mparent() == translate assert len(translate.mchildren()) == 3 # SUB PLUGS GENERAL METHOD assert len(matworld) == len(matworld.msubPlugs()) assert translate.numChildren() == len(translate.msubPlugs()) assert len(translate.msubPlugs()) == 3 # ARRAY CONNECTIONS ################### objset = nt.createNode("set1", "objectSet") partition = nt.createNode("partition1", "partition") pma = nt.createNode("plusMinusAverage1", "plusMinusAverage") destplug = persp.translate.mconnectToArray(pma.input3D, exclusive_connection=True) assert persp.translate.misConnectedTo(destplug) # exclusive connection should return exisiting plug assert persp.translate.mconnectToArray( pma.input3D, exclusive_connection=True) == destplug # but newones can also be created assert persp.translate.mconnectToArray( pma.input3D, exclusive_connection=False) != destplug #assert objset.partition.mconnectToArray( partition.sets, exclusive_connection = False ) != destplug # assure the standin classes are there - otherwise my list there would # bind to the standins as the classes have not been created yet plugs = [matworld, translate] for plug in plugs: plug.mwrappedAttribute() # CHECK ATTRIBUTES and NODES for plug, attrtype in zip(plugs, [nt.TypedAttribute, nt.CompoundAttribute]): attr = plug.mwrappedAttribute() assert isinstance(attr, nt.Attribute) assert isinstance(attr, attrtype) node = plug.mwrappedNode() assert isinstance(node, nt.Node) assert node == persp # UNDO / REDO ############## cam = nt.createNode("myTrans", "transform") testdb = [(cam.visibility, "Bool", True, False), (cam.tx, "Double", 0.0, 2.0)] # TODO: Add all missing types ! for plug, typename, initialval, targetval in testdb: getattrfunc = getattr(plug, "as" + typename) setattrfunc = getattr(plug, "mset" + typename) assert getattrfunc() == initialval setattrfunc(targetval) assert getattrfunc() == targetval cmds.undo() assert getattrfunc() == initialval cmds.redo() assert getattrfunc() == targetval # END for each tuple in testdb # TEST EVERYTHING ################# # This part has been written to be very sure every customized method gets # called at least once. I don't trust my 'old' tests, although they do # something and are valuable to the testing framework. nwnode = nt.Network() persp.msg.mct(nwnode.affectedBy.elementByLogicalIndex(0)) front.msg.mct(nwnode.affectedBy.elementByLogicalIndex(1)) t = persp.translate tx = persp.tx wm = persp.wm a = nwnode.affectedBy a.evaluateNumElements() assert len(wm) == 1 and len(a) == 2 assert isinstance(iter(wm).next(), api.MPlug) assert len(list(a)) == 2 # test str/repr assert str(wm) != str(a) assert repr(wm) != str(wm) assert wm != a # is it really necessary to apply custom handling here ? Check __eq__ method # test comparison assert a[0] == a[0] assert a[0] != a[1] # mparent assert tx.mparent() == t assert a[0].mparent() == a # mchildren assert len(a[0].mchildren()) == 0 assert len(t.mchildren()) == 3 # mchildByName assert t.mchildByName('tx') == tx self.failUnlessRaises(TypeError, tx.mchildByName, 'something') self.failUnlessRaises(AttributeError, t.mchildByName, 'doesntexist') # msubPlugs assert len(t.msubPlugs()) == 3 assert len(a.msubPlugs()) == 2 assert len(tx.msubPlugs()) == 0 # msetLocked tx.msetLocked(1) assert tx.isLocked() tx.msetLocked(0) assert not tx.isLocked() # msetKeyable tx.msetKeyable(0) assert not tx.isKeyable() tx.msetKeyable(1) assert tx.isKeyable() # msetCaching tx.msetCaching(0) #assert not tx.isCachingFlagSet() # for some reason, the caching cannot be changed here tx.msetCaching(1) assert tx.isCachingFlagSet() == 1 # msetChannelBox tx.msetChannelBox(0) assert not tx.isChannelBoxFlagSet() tx.msetChannelBox(1) assert tx.isChannelBoxFlagSet() == 1 # mconnectMultiToMulti # is tested elsewhere # connectTo self.failUnlessRaises(RuntimeError, persp.msg.mconnectTo, a[1], force=False) # already connected front.msg.mconnectTo(a[1], force=False) # already connected front.msg.mconnectTo(a[0], force=True) # force breaks connections persp.msg.mconnectTo(a[0]) # default is force # mconnectToArray # sufficiently tested ( -> st ) # mdisconnect # st # mdisconnectInput # st # mdisconnectOutputs # st # mdisconnectFrom # st # mdisconnectNode # st # mhaveConnection assert api.MPlug.mhaveConnection( front.msg, a[1]) and api.MPlug.mhaveConnection(a[1], front.msg) assert not api.MPlug.mhaveConnection( persp.msg, a[1]) and not api.MPlug.mhaveConnection( a[1], persp.msg) # misConnectedTo # st # moutputs assert len( front.msg.moutputs()) == 1 and front.msg.moutputs()[0] == a[1] assert len(a[0].moutputs()) == 0 # moutput # st # minputs assert len(a.minputs()) == 2 assert len(a[1].minputs()) == 1 # miterGraph # st # miterInputGraph # st # miterOutputGraph # st # minput # st # mconnections assert len(front.msg.mconnections()) == 2 assert len(a[1].mconnections()) == 2 # mdependencyInfo m = nt.Mesh() assert len(m.outMesh.maffected()) assert isinstance(m.outMesh.maffected()[0], api.MPlug) assert m.outMesh.maffected() == m.outMesh.mdependencyInfo(by=True) assert isinstance(m.inMesh.maffects(), list) # no affected items for some reason assert m.inMesh.maffects() == m.inMesh.mdependencyInfo(by=False) # mnextLogicalIndex|plug assert a.mnextLogicalIndex() == 2 assert a.mnextLogicalPlug().logicalIndex() # mwrappedAttribute assert isinstance(a.mwrappedAttribute(), nt.Attribute) # mwrappedNode assert isinstance(a.mwrappedNode(), nt.Node) # masData nt.PolyCube().output.mconnectTo(m.inMesh) # need data here assert isinstance(m.outMesh.masData(), nt.Data) # mfullyQualifiedName assert a.mfullyQualifiedName() != a.partialName()
def test_plugin_handling(self): mrp = "Mayatomr" pp = 'persistence' assert not cmds.pluginInfo(mrp, q=1, loaded=1) assert not hasattr(nt, 'Transmat') cmds.loadPlugin(mrp) # loading a plugin will add the node types assert hasattr(nt, 'Transmat') assert nt.typ.nodeTypeTree.has_node('transmat') tmat = nt.Transmat() # mr dep node tmat.delete() dll = nt.MapVizShape() # mr dag node assert isinstance(dll, nt.DagNode) dll.delete() cmds.flushUndo() # make sure we get rid of the custom data # custom node types are favored and not overwritten by dummies when # loading assert nt.StorageNode is mstorage.StorageNode # custom node types will remain when unloaded cmds.unloadPlugin(pp) assert not cmds.pluginInfo(pp, q=1, loaded=1) assert hasattr(nt, 'StorageNode') # unloading a plugin will remove the nodetypes as well as the hierarchy # entries # NOTE: on OSX unloading the plugin beautifully crashes maya, probably # a memory exception as MR claims to have had a peak memory of 136 GB # As a final goal, this test should be fixed to run here, there # probably is some kind of workaround. # http://tracking.byronimo.de/view.php?id=144 if sys.platform != 'darwin': cmds.unloadPlugin(mrp, force=1) assert not hasattr(nt, 'Transmat') assert not hasattr(nt, 'MapVizShape') assert not nt.typ.nodeTypeTree.has_node('transmat') assert not nt.typ.nodeTypeTree.has_node('mapVizShape') # plugins required by a scene trigger the database to update as well assert not cmds.pluginInfo(mrp, q=1, loaded=1) mrvmaya.Scene.open(get_maya_file('needsMayatomr.ma'), force=True) assert hasattr(nt, 'Transmat') # END skip this on osx # dynamically added types ( which will not trigger a plugin changed event ) # can be wrapped as well customMI = get_maya_file('customshader.mi') csn = "testCustomShader" csnc = "TestCustomShader" mrvmaya.Mel.mrFactory('-load',customMI) # it doesnt exist, but can be wrapped nontheless, then it exists assert not hasattr(nt, csnc) cs = nt.Node(cmds.createNode(csn)) assert hasattr(nt, csnc)