Python Reference Guide
 
Loading...
Searching...
No Matches
Samples\PointCache\CharacterPointCache.py
1# Copyright 2011 Autodesk, Inc. All rights reserved.
2# Use of this software is subject to the terms of the Autodesk license agreement
3# provided at the time of installation or download, or which otherwise accompanies
4# this software in either electronic or hard copy form.
5#
6# Script description:
7# Create a tool to demonstrate the Character based point cache creation workflow.
8#
9# Topic: FBPointCacheManager
10#
11import os
12
13from pyfbsdk import *
14from pyfbsdk_additions import *
15
16
17class PointCache():
18 def __init__(self):
19 self.lSystem = FBSystem()
20 self.lScene = FBSystem().Scene
21 self.lSysOnUIIdle = self.lSystem.OnUIIdle
22 self.lSysStory = FBStory()
23 self.lSysPlayer = FBPlayerControl()
24 self.lSysPcMgr = FBPointCacheManager()
25
26 self.SelectedList = []
27 self.CacheStopTime = self.lSysPlayer.ZoomWindowStop
28 self.DuplicatedModel = False
29 self.DisableEvaluationAfterCache = True
30 self.EnableInPlaceCacheDeformer = True
31 self.getDefaultPath()
32 self.TabTypes = ('Characters', 'Story Tracks')
33
34
35 def getDefaultPath(self):
36 """
37 get default path from loaded file. If path is None, use
38 the current working directory
39 """
40 if not FBApplication().FBXFileName:
41 self.DefaultPath = os.getcwd()
42 else:
43 self.DefaultPath = os.path.dirname(FBApplication().FBXFileName)
44
45 def resetButtons(self):
46 """
47 Restore the default state of the cache and deformer buttons
48 """
49 self.bCache.State = 0
50 self.bDeformer.State = 0
51
52
53 def update_EditInfo(self, text):
54 self.Edit_Info.Caption = repr(text)
55
56
57 def refresh_All(self):
58 """
59 Refresh gui elements. Have GUI elements retreive values from variables
60 """
61 self.refresh_CharacterList()
62 self.refresh_StoryTrackList()
63 self.refresh_DefaultPath()
64 self.update_EditInfo("Refresh Complete")
65
66
67 def refresh_CharacterList(self):
68 """
69 Refresh character list
70 """
71 self.CharacterListWidget.Items.removeAll()
72 for lCh in self.lScene.Characters:
73 self.CharacterListWidget.Items.append(lCh.LongName)
74
75
76 def refresh_StoryTrackList(self):
77 """
78 Refresh story track list, limited to character tracks for simplicity
79 """
80 self.StoryTrackListWidget.Items.removeAll()
81 for lTrack in self.lSysStory.RootFolder.Tracks:
82 if lTrack.Type == FBStoryTrackType.kFBStoryTrackCharacter:
83 self.StoryTrackListWidget.Items.append("%s (%s)" %(lTrack.Name,lTrack.Character.LongName))
84
85
86 def refresh_DefaultPath(self):
87 """
88 Refresh the default cache save to path
89 """
90 self.Edit_DefaultPath.Text = self.DefaultPath
91
92
93 def getSelectedList(self):
94 """
95 collect selected from active tab
96 """
97 self.SelectedList = []
98
99 currentTab = self.tab.TabPanel.Items[self.tab.TabPanel.ItemIndex]
100 if currentTab == 'Characters':
101 for lCharacter in self.lScene.Characters:
102 lName = lCharacter.LongName
103 for lItemIndex in range(len(self.CharacterListWidget.Items)):
104 if self.CharacterListWidget.IsSelected(lItemIndex) and self.CharacterListWidget.Items[lItemIndex] == lName:
105 self.SelectedList.append(lCharacter)
106 else:
107 for lTrack in self.lSysStory.RootFolder.Tracks:
108 if lTrack.Type == FBStoryTrackType.kFBStoryTrackCharacter:
109 lName = lTrack.Character.LongName
110 for lIndex, lItem in enumerate(self.StoryTrackListWidget.Items):
111 if self.StoryTrackListWidget.IsSelected(lIndex) and lTrack.Character.LongName == lName:
112 self.SelectedList.append(lTrack.Character)
113
114
115 def activeCharacterEvaluation(self, pCharacterList, pEnable):
116 """
117 function to enable/disable the character evaluation (control rig, or story track)
118 """
119 for pCharacter in pCharacterList:
120 pCharacter.Active = pEnable # Turn on/off character solving
121 for lTrack in self.lSysStory.RootFolder.Tracks:
122 if lTrack.Type == FBStoryTrackType.kFBStoryTrackCharacter and lTrack.Character == pCharacter:
123 lTrack.Mute = (not pEnable) # Turn on/off story character track
124
125
126 def activeCharacterInPlaceCacheDeformer(self, pEnable):
127 """
128 Active Character Skin Model In place cache deformer
129 """
130 self.getSelectedList()
131 if len(self.SelectedList) == 0:
132 self.update_EditInfo( "Nothing selected for caching!")
133 return False
134
135 lSkinModelList = FBModelList()
136 for lCh in self.SelectedList:
137 print(lCh.LongName)
138 lCh.GetSkinModelList(lSkinModelList)
139
140 for lSkinModel in lSkinModelList:
141 self.update_EditInfo(lSkinModel.LongName)
142 lSkinModel.PointCacheDeformable = pEnable
143
144 # In Place Cache Create with the first frame's transform as reference
145 self.lSysPlayer.GotoStart()
146 self.activeCharacterEvaluation(self.SelectedList, (not pEnable));
147
148
149 def recordIdleCallback(self, pObject, pEventName):
150 """
151 Record Idle Callback to control the record period
152 """
153 if self.lSysPlayer.IsPlaying:
154 if self.lSystem.LocalTime.GetSecondDouble() >= self.CacheStopTime.GetSecondDouble() :
155 self.lSysOnUIIdle.Remove(self.recordIdleCallback)
156 self.lSysPlayer.GotoStart()
157 if self.DisableEvaluationAfterCache == True:
158 self.activeCharacterEvaluation(self.SelectedList, False)
159
160
161 def configurePointCacheManager(self):
162 """
163 Configure the Point Cache Manager
164 """
165 self.lSysPcMgr.ApplyGlobalTransform = True
166 self.lSysPcMgr.AlwaysAskForPath = False
167 self.lSysPcMgr.DefaultPath = self.DefaultPath
168
169
170
171 def list_OnChange(self, pList, event):
172 """
173 UI Callback
174 """
175 for lItemIndex in range(len(pList.Items)):
176 if pList.IsSelected(lItemIndex):
177 self.update_EditInfo(pList.Items[lItemIndex] + " has been selected!")
178
179
180 def refreshAll_OnClick(self,control=None, event=None):
181 """
182 UI Callback
183 """
184 self.refresh_All()
185
186
187 def duplicateCheckBox_OnClick(self, pCheckBox, event):
188 """
189 UI Callback
190 """
191 self.DuplicatedModel = (pCheckBox.State != 0)
192 self.update_EditInfo(self.DuplicatedModel)
193
194
195 def disableEvalBtn_OnClick(self, pCheckBox, event):
196 """
197 UI Callback
198 """
199 self.DisableEvaluationAfterCache = (pCheckBox.State != 0)
200 self.update_EditInfo(self.DisableEvaluationAfterCache)
201
202
203 def cacheStartTime_OnChange(self, pTimeCode, event):
204 """
205 UI Callback
206 """
207 self.CacheStopTime = pTimeCode.Value
208 self.update_EditInfo(self.CacheStopTime)
209
210
211 def defaultPathEdit_OnChange(self, pEdit, event):
212 """
213 UI Callback
214 """
215 self.DefaultPath = pEdit.Text
216
217
218 def defaultPath_OnClick(self, control, event):
219 """
220 Path Callback
221 """
222 lFp = FBFolderPopup()
223 lFp.Caption = "Choose save location for Point Cache files"
224 lFp.Path = self.DefaultPath
225 lRes = lFp.Execute()
226
227 if lRes:
228 self.DefaultPath = lFp.Path
229
230 self.refresh_DefaultPath()
231
232
233 def cache_OnClick(self, control, event):
234 """
235 Cache Callback
236 """
237 self.resetButtons()
238
239 self.getSelectedList() #Select the Character Skin Models to reocrd.
240
241 if len(self.SelectedList) == 0:
242 self.update_EditInfo("No Character selected for caching!")
243 return;
244
245 lSkinModelList = FBModelList()
246 self.update_EditInfo("Create point cache for Characters:")
247 for l in self.SelectedList:
248 self.update_EditInfo(l.LongName)
249 l.GetSkinModelList(lSkinModelList)
250
251 if len(lSkinModelList) == 0:
252 self.update_EditInfo("No Recordable Skin Models Selected")
253 return
254
255 self.update_EditInfo("Create point cache for skin models:")
256 for lSkinModel in lSkinModelList:
257 self.update_EditInfo(lSkinModel.LongName)
258
259 self.configurePointCacheManager() # setup the point cache manager
260
261 self.lSysPcMgr.Models.removeAll()
262 for lSkinModel in lSkinModelList:
263 self.update_EditInfo(lSkinModel.LongName)
264 self.lSysPcMgr.Models.append(lSkinModel) #Add model to be recorded
265
266 self.lSysPlayer.GotoStart()
267 self.lSysPlayer.Record(True, False)
268 self.lScene.Evaluate() #Important, to allow setup take effects.
269
270 if not self.lSysPlayer.IsRecording:
271 return
272
273 if self.DuplicatedModel:
274 self.lSysPcMgr.ApplyCacheOnNewModel = True
275 else:
276 self.update_EditInfo("Cache No Duplication")
277 self.lSysPcMgr.ApplyCacheOnNewModel = False
278 # Set Transformation Reference, we need to turn off the Character Evaluation first.
279 self.activeCharacterEvaluation(self.SelectedList, False)
280 self.lScene.Evaluate() # Important, to allow setup take effects.
281 self.lSysPcMgr.SetTransformReference()
282 # Restore Character Evaluation
283 self.activeCharacterEvaluation(self.SelectedList, True)
284 self.lScene.Evaluate() # Important, to allow setup take effects.
285
286 self.lSysOnUIIdle.Add(self.recordIdleCallback)
287
288 self.lSysPlayer.Play() # Record
289
290
291 def enableCache_OnClick(self, control, event):
292 """
293 UI Callback
294 """
295 self.activeCharacterInPlaceCacheDeformer(True)
296
297
298 def disableCache_OnClick(self, control, event):
299 """
300 UI Callback
301 """
302 self.activeCharacterInPlaceCacheDeformer(False)
303
304
305
306
307
308 def populateLayout(self, mainLyt):
309 """
310 Layout management & callback hookup
311 """
312 x = FBAddRegionParam(5,FBAttachType.kFBAttachLeft,"")
313 y = FBAddRegionParam(5,FBAttachType.kFBAttachTop,"")
314 w = FBAddRegionParam(-5,FBAttachType.kFBAttachRight,"")
315 h = FBAddRegionParam(-5,FBAttachType.kFBAttachBottom,"")
316 mainLyt.AddRegion("main","main", x,y,w,h)
317
318 grid = FBGridLayout()
319 mainLyt.SetControl("main", grid)
320
321 label = FBLabel()
322 label.Caption = "Choose from a list of characters or a list of character story tracks"
323 grid.AddRange(label, 0, 0, 0, 4)
324
325 bRefresh = FBButton()
326 bRefresh.Caption = "Refresh"
327 bRefresh.Justify = FBTextJustify.kFBTextJustifyCenter
328 grid.Add(bRefresh, 0, 4)
329 bRefresh.OnClick.Add(self.refreshAll_OnClick)
330
331 self.tab = FBTabControl()
332
333 for name in self.TabTypes:
334
335 l = FBVBoxLayout()
336 x = FBAddRegionParam(10,FBAttachType.kFBAttachLeft,"")
337 y = FBAddRegionParam(10,FBAttachType.kFBAttachTop,"")
338 w = FBAddRegionParam(-10,FBAttachType.kFBAttachRight,"")
339 h = FBAddRegionParam(-10,FBAttachType.kFBAttachBottom,"")
340 l.AddRegion(name,'', x, y, w, h)
341
342 # provide a scrolling list
343 scroll = FBScrollBox()
344 l.SetControl('test',scroll)
345
346 lLabel = FBLabel()
347 lLabel.Caption = "Choose %s(s) for operation:" % name
348 l.Add(lLabel, 16)
349
350 if name == 'Characters':
351 self.CharacterListWidget = FBList()
352 self.CharacterListWidget.OnChange.Add(self. list_OnChange)
353 self.CharacterListWidget.Style = FBListStyle.kFBVerticalList
354 self.CharacterListWidget.MultiSelect = True
355 l.Add(self.CharacterListWidget, 141)
356 else:
357 self.StoryTrackListWidget = FBList()
358 self.StoryTrackListWidget.OnChange.Add(self. list_OnChange)
359 self.StoryTrackListWidget.Style = FBListStyle.kFBVerticalList
360 self.StoryTrackListWidget.MultiSelect = True
361 l.Add(self.StoryTrackListWidget, 141)
362
363 self.tab.Add(name,l)
364
365 self.tab.SetContent(0)
366 self.tab.TabPanel.TabStyle = 0
367 grid.AddRange(self.tab, 1, 7, 0, 4)
368
369 lPCOptionsLayout = FBHBoxLayout()
370 grid.AddRange(lPCOptionsLayout,8, 8, 0, 4)
371
372 bDupMod = FBButton()
373 bDupMod.Caption = "Duplicate Model"
374 bDupMod.Style = FBButtonStyle.kFBCheckbox
375 bDupMod.Justify = FBTextJustify.kFBTextJustifyCenter
376 bDupMod.State = self.DuplicatedModel
377 lPCOptionsLayout.Add(bDupMod,105)
378 bDupMod.OnClick.Add(self.duplicateCheckBox_OnClick)
379
380 bDeactivate = FBButton()
381 bDeactivate.Caption = "Deactive Eval After Cache"
382 bDeactivate.Style = FBButtonStyle.kFBCheckbox
383 bDeactivate.Justify = FBTextJustify.kFBTextJustifyCenter
384 bDeactivate.State = self.DisableEvaluationAfterCache
385 lPCOptionsLayout.Add(bDeactivate,160)
386 bDeactivate.OnClick.Add(self.disableEvalBtn_OnClick)
387
388 lLabel = FBLabel()
389 lLabel.Caption = "Cache End Time:"
390 lLabel.Justify = FBTextJustify.kFBTextJustifyRight
391 lPCOptionsLayout.Add(lLabel, 90)
392
393 eCacheEndTime = FBEditTimeCode()
394 eCacheEndTime.Caption = "Cache End Time"
395 eCacheEndTime.Value = self.CacheStopTime
396 eCacheEndTime.OnChange.Add(self.cacheStartTime_OnChange)
397 lPCOptionsLayout.Add(eCacheEndTime,60)
398
399 lPCPathLayout = FBHBoxLayout()
400 grid.AddRange(lPCPathLayout,9, 9, 0, 4)
401 lLabel = FBLabel()
402 lLabel.Caption = "Cache file path"
403 lLabel.Justify = FBTextJustify.kFBTextJustifyRight
404 lPCPathLayout.Add(lLabel,75)
405
406 self.Edit_DefaultPath = FBEdit()
407 self.Edit_DefaultPath.OnChange.Add(self.defaultPathEdit_OnChange)
408 lPCPathLayout.AddRelative(self.Edit_DefaultPath, 1)
409
410 bFileDialog = FBButton()
411 bFileDialog.Caption = "..."
412 bFileDialog.Justify = FBTextJustify.kFBTextJustifyCenter
413 lPCPathLayout.Add(bFileDialog,22)
414 bFileDialog.OnClick.Add(self.defaultPath_OnClick)
415
416 bProcessCache = FBButton()
417 bProcessCache.Caption = "Process Cache"
418 bProcessCache.Justify = FBTextJustify.kFBTextJustifyCenter
419 grid.AddRange(bProcessCache,10, 10, 0, 4)
420 bProcessCache.OnClick.Add(self.cache_OnClick)
421
422 lLabel = FBLabel()
423 lLabel.Caption = "View as:"
424 lLabel.Justify = FBTextJustify.kFBTextJustifyRight
425 grid.Add(lLabel,11, 0)
426
427 # bCache is a class attribute rather than a method attribute because
428 # it is accessed in another method
429 self.bCache = FBButton()
430 self.bCache.Caption = "Cache"
431 self.bCache.Style = FBButtonStyle.kFB2States
432 self.bCache.Look = FBButtonLook.kFBLookPush
433 self.bCache.Justify = FBTextJustify.kFBTextJustifyCenter
434 grid.AddRange (self.bCache,11, 11, 1, 2)
435 self.bCache.OnClick.Add(self.enableCache_OnClick)
436
437 # bDeformer is a class attribute rather than a method attribute because
438 # it is accessed in another method
439 self.bDeformer = FBButton()
440 self.bDeformer.Caption = "Deformer"
441 self.bDeformer.Style = FBButtonStyle.kFB2States
442 self.bDeformer.Look = FBButtonLook.kFBLookPush
443 self.bDeformer.Justify = FBTextJustify.kFBTextJustifyCenter
444 grid.AddRange(self.bDeformer,11, 11, 3, 4)
445 self.bDeformer.OnClick.Add(self.disableCache_OnClick)
446
447 #group these buttons for better UI visuals
448 group = FBButtonGroup()
449 group.Add(self.bCache)
450 group.Add(self.bDeformer)
451
452 self.Edit_Info = FBLabel()
453 self.Edit_Info.Caption = ''
454 grid.AddRange(self.Edit_Info,12, 12, 0, 4)
455
456 # refresh all of the gui elements in order to get relevant data
457 self.refresh_All()
458
459
460
461
462def createTool():
463 """
464 Tool creation will serve as the hub for all other controls
465 """
466 t = FBCreateUniqueTool("Character Based Point Cache Example")
467 t.StartSizeX = 615
468 t.MinSizeX = 455
469 t.MinSizeY = 450
470 t.MaxSizeY = 450
471
472 pc = PointCache()
473
474 pc.populateLayout(t)
475 ShowTool(t)
476
477createTool()
478
FBApplication is used mainly to manage files.
Definition: pyfbsdk_generated.h:801
Used to create and manage buttons in a user interface.
Definition: pyfbsdk_generated.h:2442
Text edit box.
Definition: pyfbsdk_generated.h:5998
Definition: pyfbsdk_generated.h:6131
Folder Popup (for selecting a directory).
Definition: pyfbsdk_generated.h:8126
Text label.
Definition: pyfbsdk_generated.h:9829
List of items.
Definition: pyfbsdk_generated.h:10156
Player control.
Definition: pyfbsdk_generated.h:13745
Point Cache Manager Interface to the point cache manager.
Definition: pyfbsdk_generated.h:14276
Scroll Box.
Definition: pyfbsdk_generated.h:16979
Story Management class.
Definition: pyfbsdk_generated.h:17689
Provides access to the underlying system, and the MotionBuilder scene.
Definition: pyfbsdk_generated.h:18771