-
Notifications
You must be signed in to change notification settings - Fork 6
/
bwParticleToBubblePop.py
229 lines (154 loc) · 11.1 KB
/
bwParticleToBubblePop.py
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
'''
###########################################################################
name: bwParticleToBubblePop -- Oct 2015
Created by: Bryan Woodard & Chris Jones(github.com/csjones
This script will build a curve and attach a locator to the
curve using the pathAnimation command (motion path). It will then build
a simple sphere and give it specific nCloth properties
Use: make sure you have an nParticle named nParticle1 in the scene.
Future updates - update so selected nParticle systems can work. Also update
attributes for nCloth.
version history
v0.1 - scipt has the ability to make bubbles
v0.2 - User must select any nParticle
- Some added error handling
- Can now pop bubbles
Tested on Maya 2016 for Windows
Use at your own risk
############################################################################
'''
import maya.cmds as mc
import random
import maya.mel as mel
inc=0
getSelPartiShape = mc.ls(sl=True, dag=True, lf=True)
minFrames = mc.playbackOptions( q=True, min=True)
maxFrames = mc.playbackOptions( q=True, max=True)
for shapeSel in getSelPartiShape:
if "nParticle" == mc.objectType(shapeSel):#check and make sure that what we have selected are nParticles.
allParticleDictionary = {}
getTrans = mc.pickWalk(shapeSel, d="up")
theParticle = mc.ls(getTrans, type = "transform")
everyThingFolder = mc.group(em=True, n=(theParticle[0] + "_GRP"))
print theParticle #since there is no progress bar this let's the user know which particle is being processed.
for currentFrame in range(0, int(maxFrames)):
#print('Frame=' + str(currentFrame))
mc.currentTime(currentFrame, update=True, edit=True)
for part in theParticle:
for particleCount in range(0,mc.particle(part, q=True,ct=True)):
particleName = mc.particle(part, q=True, order=particleCount, at='id')
particlesPosition = mc.particle(part, q=True, order=particleCount, at='position')
particleDictionary = {}
if str(particleName[0]) in allParticleDictionary.keys():
particleDictionary = allParticleDictionary[str(particleName[0])]
particleDictionary[currentFrame] = particlesPosition
allParticleDictionary[str(particleName[0])] = particleDictionary
for curveParticleId in allParticleDictionary.keys():
pointList = []
sortedKeyFrameList = sorted(allParticleDictionary[curveParticleId].keys())
if len(sortedKeyFrameList) > 1:
for keyFrame in sortedKeyFrameList:
pointList.append(allParticleDictionary[curveParticleId][keyFrame])
grpFolder = mc.group(em=True, n="smBubbleGroup" + str(inc))
curveName = "partiCurve" + str(curveParticleId)
curveObj = mc.curve(name = curveName, p = pointList)
locName = "locatorName" + str(curveParticleId)
locObj = mc.spaceLocator(name = (locName+theParticle[0]))
mc.pathAnimation(locObj, stu=sortedKeyFrameList[0], etu=sortedKeyFrameList[-1] ,c=curveObj,n=("moPath_" + theParticle[0]))
#For every locator we create, make a bubble and attach that to the locator in worldspace and parent in underneath
makeBubble = mc.polyCube(name=("bubble" + str(inc)), w=.1, h=.1, d=.1, sx=8, sy=8, sz=8)
mc.sculpt(makeBubble, maxDisplacement=.1)
mc.delete(makeBubble, ch=True)
getPos = mc.xform(locObj, ws=True, q=True, translation=True)
mc.xform(makeBubble[0], t=(getPos[0], getPos[1], getPos[2]))
mc.parent(makeBubble[0], locObj)
randBubbleSize = random.uniform(.2, .5)#This is what will give our bubbles the random size
mc.scale(randBubbleSize, randBubbleSize, randBubbleSize, makeBubble[0])
#Create nCloth for each bubble and set the collide strength to turn on when the bubble moves, never before.
mc.select(makeBubble[0])
mc.nClothCreate()
bubbleNClothName = mc.rename("nCloth1", ("nClothBub" + str(inc)))
#mc.setAttr(locObj + ".collideStrength", 0)
mc.setKeyframe(bubbleNClothName, attribute='collideStrength', t=[sortedKeyFrameList[0], sortedKeyFrameList[-1]])
mc.setAttr(bubbleNClothName + ".collideStrength", 0)
mc.setKeyframe(bubbleNClothName, attribute='collideStrength', t=[sortedKeyFrameList[0]-1, sortedKeyFrameList[-1]+1])
mc.setKeyframe(bubbleNClothName, attribute='rigidity', t=[sortedKeyFrameList[0], sortedKeyFrameList[-1]+10])
mc.setAttr(bubbleNClothName + ".rigidity", .1)
mc.setKeyframe(bubbleNClothName, attribute='rigidity', t=[sortedKeyFrameList[0]+10, sortedKeyFrameList[-1]])
mc.setAttr(bubbleNClothName + ".inputMeshAttract", .7)
mc.setKeyframe(bubbleNClothName, attribute='inputMeshAttract', t=[sortedKeyFrameList[0], sortedKeyFrameList[-1]+10])
mc.setAttr(bubbleNClothName + ".inputMeshAttract", .3)
mc.setKeyframe(bubbleNClothName, attribute='inputMeshAttract', t=[sortedKeyFrameList[0]+10, sortedKeyFrameList[-1]])
mc.setAttr(bubbleNClothName + ".stretchResistance", 20)
mc.setAttr(bubbleNClothName + ".compressionResistance", 80)
mc.setAttr(bubbleNClothName + ".selfCollisionFlag", 4)
mc.setAttr(bubbleNClothName + ".trappedCheck", 1)
mc.setAttr(bubbleNClothName + ".pressure", 3)
mc.setAttr(bubbleNClothName + ".pointMass", .4)
mc.setAttr(bubbleNClothName + ".isDynamic", 0)
exprShpName = mc.pickWalk(bubbleNClothName, d="down")
#set the visibiliy of the LOCATORS on when it's moving and off when it has stopped
setOn = mc.setKeyframe( locObj[0], attribute='visibility', t=[sortedKeyFrameList[0], sortedKeyFrameList[-1]])
mc.setAttr(locObj[0] + ".visibility", 0)
setOff = mc.setKeyframe( locObj[0], attribute='visibility', t=[sortedKeyFrameList[0]-1, sortedKeyFrameList[-1]+1])
#########EXPRESSION TIME################ All examples below are not currently working but different techniques I tried to solve the problem so far
#This needs to occur because the computer can't handle this many nCloth items being alive at the same time.
#theExpression = mc.expression(name = "bubbleExp", string = "if(frame <= " + str(sortedKeyFrameList[0]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(0) + ";" + '\n' + "if(frame > " + str(sortedKeyFrameList[0]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" +'" ' + str(1) + ";" + '\n' + "if(frame > " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(0) + ";")
#theExpression = mc.expression(name = "bubbleExp", string = "if(frame <= " + str(sortedKeyFrameList[0]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(0) + ";" + '\n' + "else if(frame > " + str(sortedKeyFrameList[0]) + " && " + "frame < " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" +'" ' + str(1) + ";" + '\n' + "else" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(0) + ";")
#theExpression = mc.expression(name = "bubbleExp", string = "if(frame <= " + str(sortedKeyFrameList[0]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(0) + ";" + '\n' + "if(frame > " + str(sortedKeyFrameList[0]) + "&&" + "frame < " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" +'" ' + str(1) + ";")
#theExpression = mc.expression(name = "bubbleExp", string = "if(frame <= " + str(sortedKeyFrameList[0]-5) + " || " "frame > " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(0) + ";" + '\n' + "else if(frame >= " + str(sortedKeyFrameList[0]-4) + " && " + "frame <= " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" +'" ' + str(1) + ";")
#theExpression = mc.expression(name = "bubbleExp", string = "if(frame >= " + str(sortedKeyFrameList[0]-4) + " && " + "frame <= " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" + '" ' + str(1) + ";" + '\n' + "else if(frame <= " + str(sortedKeyFrameList[0]-5) + " || " "frame > " + str(sortedKeyFrameList[-1]) + ")" + '\n' + " setAttr " + '"' + exprShpName[0] + ".isDynamic" +'" ' + str(0) + ";")
######################### BUBBLE POP TIME #############################################
#pop the bubble - we know there are 152 vers in the bubble. Pick a random number in that and go up and down from that number by 35 to get random selections
getRandNum = random.randint(34,300) #this is 35 above 0 and 35 below 151 so that we don't reach higher
randVertValHi = getRandNum + 35
randVertValLo = getRandNum - 35
print getRandNum
mc.select(makeBubble[0] + ".vtx[" + str(randVertValLo) + ":" + str(randVertValHi) + "]")
makeTearable = mel.eval('createNConstraint tearableSurface false;')
#Increase pressure before the tear happens
mc.setKeyframe(bubbleNClothName, attribute='pres', t=[sortedKeyFrameList[-1]-3])
mc.setAttr(bubbleNClothName + ".pres", 10)
mc.setKeyframe(bubbleNClothName, attribute='pres', t=[sortedKeyFrameList[-1]-2])
#Tear it apart 10frames before it ends its run
mc.setKeyframe(makeTearable, attribute='gls', t=[sortedKeyFrameList[-1]-2])
mc.setAttr(makeTearable[0] + ".glueStrength", 0)
mc.setKeyframe(makeTearable, attribute='gls', t=[sortedKeyFrameList[-1]-1])
#######################################################################
#place the newly created objects into nCloth_Objs folder
inc += 1
mc.parent(locObj,curveObj,bubbleNClothName,makeTearable, grpFolder)
mc.parent(grpFolder, everyThingFolder)
else:
print("The item selected doesn't appear to be an nCloth object --> " + shapeSel + " <--")
#check to see if the nCloth is enabled and if so turn it off so the next round of bubbles isn't slow
getnClothEnabledItmes = mc.ls(type='nCloth')#this is a dumb way to grab things
if len(getnClothEnabledItmes) > 0:
for item in getnClothEnabledItmes:
print item
mc.setAttr(item + ".isDynamic", 1)
mc.currentTime(1)
'''
mc.select("nClothBub*")
'''
'''
After you cache the bubbles this part will select the
bubbles and move the cache to the input mesh and
then display the input mesh, now ready to be exported.
NOTE -- the key to this working is that the input mesh
has all the cuts in the edges allowing for a static value
in the vert count, otherwise this wouldn't work.
import maya.mel as mel
mc.select('bubble*')#If there are other objects in the scene that start with bubble you may be selecting it, be careful
getTheBubble = mc.ls(sl=True, tr=True)
bubbleToExportSet = mc.sets(getTheBubble ,n="bubblesToExport")
for bubble in getTheBubble:
mc.select(bubble)
mel.eval('moveCacheToInput 0;')
mel.eval('displayNClothMesh "input";')
print bubble
mc.select("locatorName*")
#To delete the expressions if they're turned back on again
mc.select("bubbleExp*")
mc.delete()
'''