forked from dgovil/PythonForMayaSamples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgears2.py
More file actions
117 lines (95 loc) · 5.51 KB
/
Copy pathgears2.py
File metadata and controls
117 lines (95 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""
In this code sample, we'll convert the functions we created earlier to make a gear, into a class.
A class is a python object that lets you contain functions that relate to a specific object easily
It will be a little different then the one in the video, because I've added a few more methods, but it should be easy to follow along.
"""
import maya.cmds as cmds
# The class keyword creates a class, ours will be called Gear
# We will base our class on the python 'object'
# Object is the base for everything in python, and by basing off of the python 'object' we get all of its
# attributes for free
class Gear(object):
"""
Classes can have docstrings too that will describe how to use it
In this case you would use it like this
# This creates an instance of the class.
# Classes descrive an object, instances are the objects that they describe
# For example an Animal class describes an animal, but a dog on the street would be an instance of an Animal
gearA = Gear()
gearA.create(teeth=20, length=0.2)
gearA.changeTeeth(teeth=10, length=0.5)
"""
# The __init__ function is something that classes use a lot
# They get run whenever you initialize a new instance of a class
# For example when you do this gearA = Gear() it will run the __init__
# You can think of them as the entryway to a class that tells it how to set up
#
# Most functions inside a class will take a first parameter called self that tells it to refer to itself.
# Kind of like how you need to know you are yourself, the self parameter tells an instance it is itself
def __init__(self):
# We will just use this __init__ to create placeholder variables on the class
# Variables that start with self are set on the instance and can be accessed outside this function
self.shape = None
self.transform = None
self.constructor = None
self.extrude = None
# Another thing, functions inside a class are called methods
def create(self, teeth=10, length=0.3):
# The logic here is the same as in the functional version of this
spans = teeth * 2
# We refer to the createPipe method with self because we want to know to call the method that is inside this class
# Notice we aren't getting a variable back from this method
# Because we will store the variables on the class, we don't have to pass around them from a return (though we can if we choose to)
self.createPipe(spans)
# Similarly we call self.makeTeeth which is a method inside this class
self.makeTeeth(teeth=teeth, length=length)
def createPipe(self, spans):
# We set the transform and shape to the class variables
self.transform, self.shape = cmds.polyPipe(subdivisionsAxis=spans)
# I didn't like having to find the constructor from the extrude node
# Lets just find it now and save it to the class because it won't change
for node in cmds.listConnections('%s.inMesh' % self.transform):
if cmds.objectType(node) == 'polyPipe':
self.constructor = node
break
def makeTeeth(self, teeth=10, length=0.3):
# The logic here is exactly the same as in the makeTeeth function we created
cmds.select(clear=True)
faces = self.getTeethFaces(teeth)
for face in faces:
cmds.select('%s.%s' % (self.transform, face), add=True)
# Instead of returning a value, lets just store the extrude node onto the class as a class variable
self.extrude = cmds.polyExtrudeFacet(localTranslateZ=length)[0]
cmds.select(clear=True)
def changeLength(self, length=0.3):
# Because we stored the extrude node on the class, we can just get it directly
# This way we don't need to be told what extrude node to change
cmds.polyExtrudeFacet(self.extrude, edit=True, ltz=length)
def changeTeeth(self, teeth=10, length=0.3):
# we know what node the constructor is, so we can refer to it directly
cmds.polyPipe(self.constructor, edit=True, sa=teeth * 2)
# Then we can just call the makeTeeth directly
self.modifyExtrude(teeth=teeth, length=length)
def getTeethFaces(self, teeth):
spans = teeth * 2
sideFaces = range(spans * 2, spans * 3, 2)
faces = []
for face in sideFaces:
# Similar to what we did earlier, but using %d instead of %s
# In reality it doesn't matter, but here it means it will only accept a number
faces.append('f[%d]' % face)
return faces
def modifyExtrude(self, teeth=10, length=0.3):
faces = self.getTeethFaces(teeth)
# The extrude node has an attribute called inputComponents
# To change it we can use a simple setAttr call instead of recreating the extrude which can be expensive
# The arguments to changing a list of components is slightly different than a simple setAttr
# it is:
# cmds.setAttr('extrudeNode.inputComponents', numberOfItems, item1, item2, item3, type='componentList')
cmds.setAttr('%s.inputComponents' % self.extrude, len(faces), *faces, type='componentList')
# The *faces will be new to you.
# It basically means to expand a list in place for arguments
# so if the list has ['f[1]', 'f[2]'] etc, it will be expanded in the arguments to be like this
# cmds.setAttr('extrudeNode.inputComponents', 2, 'f[1]', 'f[2]', type='componentList'
# Finally we modify the length
self.changeLength(length)