Samples/Character/CharacterMarkerSetFromActor.py

Samples/Character/CharacterMarkerSetFromActor.py
1 # Copyright 2012 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 # Advanced script showing how to convert actor solve into character marker set.
8 # You will find in here:
9 # - how to create skeleton from actor
10 # - how to create character and characterize skeleton for it
11 # - how to create character marker set
12 # - how to query marker setup from actor and apply it on character marker set
13 # - how to change solvers on character
14 #
15 # Topic: FBCharacter FBCharacterMarkerSet FBActor
16 #
17 
18 from pyfbsdk import *
19 
20 '''
21 # helper functions
22 '''
23 lSkeletonNodeParentIds = {
24  FBSkeletonNodeId.kFBSkeletonReferenceIndex : FBSkeletonNodeId.kFBSkeletonInvalidIndex,
25  FBSkeletonNodeId.kFBSkeletonHipsIndex : FBSkeletonNodeId.kFBSkeletonReferenceIndex,
26  FBSkeletonNodeId.kFBSkeletonLeftHipIndex : FBSkeletonNodeId.kFBSkeletonHipsIndex,
27  FBSkeletonNodeId.kFBSkeletonLeftKneeIndex : FBSkeletonNodeId.kFBSkeletonLeftHipIndex,
28  FBSkeletonNodeId.kFBSkeletonLeftAnkleIndex : FBSkeletonNodeId.kFBSkeletonLeftKneeIndex,
29  FBSkeletonNodeId.kFBSkeletonLeftFootIndex : FBSkeletonNodeId.kFBSkeletonLeftAnkleIndex,
30  FBSkeletonNodeId.kFBSkeletonRightHipIndex : FBSkeletonNodeId.kFBSkeletonHipsIndex,
31  FBSkeletonNodeId.kFBSkeletonRightKneeIndex : FBSkeletonNodeId.kFBSkeletonRightHipIndex,
32  FBSkeletonNodeId.kFBSkeletonRightAnkleIndex : FBSkeletonNodeId.kFBSkeletonRightKneeIndex,
33  FBSkeletonNodeId.kFBSkeletonRightFootIndex : FBSkeletonNodeId.kFBSkeletonRightAnkleIndex,
34  FBSkeletonNodeId.kFBSkeletonWaistIndex : FBSkeletonNodeId.kFBSkeletonHipsIndex,
35  FBSkeletonNodeId.kFBSkeletonChestIndex : FBSkeletonNodeId.kFBSkeletonWaistIndex,
36  FBSkeletonNodeId.kFBSkeletonLeftCollarIndex : FBSkeletonNodeId.kFBSkeletonChestIndex,
37  FBSkeletonNodeId.kFBSkeletonLeftShoulderIndex : FBSkeletonNodeId.kFBSkeletonLeftCollarIndex,
38  FBSkeletonNodeId.kFBSkeletonLeftElbowIndex : FBSkeletonNodeId.kFBSkeletonLeftShoulderIndex,
39  FBSkeletonNodeId.kFBSkeletonLeftWristIndex : FBSkeletonNodeId.kFBSkeletonLeftElbowIndex,
40  FBSkeletonNodeId.kFBSkeletonRightCollarIndex : FBSkeletonNodeId.kFBSkeletonChestIndex,
41  FBSkeletonNodeId.kFBSkeletonRightShoulderIndex : FBSkeletonNodeId.kFBSkeletonRightCollarIndex,
42  FBSkeletonNodeId.kFBSkeletonRightElbowIndex : FBSkeletonNodeId.kFBSkeletonRightShoulderIndex,
43  FBSkeletonNodeId.kFBSkeletonRightWristIndex : FBSkeletonNodeId.kFBSkeletonRightElbowIndex,
44  FBSkeletonNodeId.kFBSkeletonNeckIndex : FBSkeletonNodeId.kFBSkeletonChestIndex,
45  FBSkeletonNodeId.kFBSkeletonHeadIndex : FBSkeletonNodeId.kFBSkeletonNeckIndex,
46  FBSkeletonNodeId.kFBSkeletonLeftThumbAIndex : FBSkeletonNodeId.kFBSkeletonLeftWristIndex,
47  FBSkeletonNodeId.kFBSkeletonLeftThumbBIndex : FBSkeletonNodeId.kFBSkeletonLeftThumbAIndex,
48  FBSkeletonNodeId.kFBSkeletonLeftThumbCIndex : FBSkeletonNodeId.kFBSkeletonLeftThumbBIndex,
49  FBSkeletonNodeId.kFBSkeletonLeftIndexAIndex : FBSkeletonNodeId.kFBSkeletonLeftWristIndex,
50  FBSkeletonNodeId.kFBSkeletonLeftIndexBIndex : FBSkeletonNodeId.kFBSkeletonLeftIndexAIndex,
51  FBSkeletonNodeId.kFBSkeletonLeftIndexCIndex : FBSkeletonNodeId.kFBSkeletonLeftIndexBIndex,
52  FBSkeletonNodeId.kFBSkeletonLeftMiddleAIndex : FBSkeletonNodeId.kFBSkeletonLeftWristIndex,
53  FBSkeletonNodeId.kFBSkeletonLeftMiddleBIndex : FBSkeletonNodeId.kFBSkeletonLeftMiddleAIndex,
54  FBSkeletonNodeId.kFBSkeletonLeftMiddleCIndex : FBSkeletonNodeId.kFBSkeletonLeftMiddleBIndex,
55  FBSkeletonNodeId.kFBSkeletonLeftRingAIndex : FBSkeletonNodeId.kFBSkeletonLeftWristIndex,
56  FBSkeletonNodeId.kFBSkeletonLeftRingBIndex : FBSkeletonNodeId.kFBSkeletonLeftRingAIndex,
57  FBSkeletonNodeId.kFBSkeletonLeftRingCIndex : FBSkeletonNodeId.kFBSkeletonLeftRingBIndex,
58  FBSkeletonNodeId.kFBSkeletonLeftPinkyAIndex : FBSkeletonNodeId.kFBSkeletonLeftWristIndex,
59  FBSkeletonNodeId.kFBSkeletonLeftPinkyBIndex : FBSkeletonNodeId.kFBSkeletonLeftPinkyAIndex,
60  FBSkeletonNodeId.kFBSkeletonLeftPinkyCIndex : FBSkeletonNodeId.kFBSkeletonLeftPinkyBIndex,
61  FBSkeletonNodeId.kFBSkeletonRightThumbAIndex : FBSkeletonNodeId.kFBSkeletonRightWristIndex,
62  FBSkeletonNodeId.kFBSkeletonRightThumbBIndex : FBSkeletonNodeId.kFBSkeletonRightThumbAIndex,
63  FBSkeletonNodeId.kFBSkeletonRightThumbCIndex : FBSkeletonNodeId.kFBSkeletonRightThumbBIndex,
64  FBSkeletonNodeId.kFBSkeletonRightIndexAIndex : FBSkeletonNodeId.kFBSkeletonRightWristIndex,
65  FBSkeletonNodeId.kFBSkeletonRightIndexBIndex : FBSkeletonNodeId.kFBSkeletonRightIndexAIndex,
66  FBSkeletonNodeId.kFBSkeletonRightIndexCIndex : FBSkeletonNodeId.kFBSkeletonRightIndexBIndex,
67  FBSkeletonNodeId.kFBSkeletonRightMiddleAIndex : FBSkeletonNodeId.kFBSkeletonRightWristIndex,
68  FBSkeletonNodeId.kFBSkeletonRightMiddleBIndex : FBSkeletonNodeId.kFBSkeletonRightMiddleAIndex,
69  FBSkeletonNodeId.kFBSkeletonRightMiddleCIndex : FBSkeletonNodeId.kFBSkeletonRightMiddleBIndex,
70  FBSkeletonNodeId.kFBSkeletonRightRingAIndex : FBSkeletonNodeId.kFBSkeletonRightWristIndex,
71  FBSkeletonNodeId.kFBSkeletonRightRingBIndex : FBSkeletonNodeId.kFBSkeletonRightRingAIndex,
72  FBSkeletonNodeId.kFBSkeletonRightRingCIndex : FBSkeletonNodeId.kFBSkeletonRightRingBIndex,
73  FBSkeletonNodeId.kFBSkeletonRightPinkyAIndex : FBSkeletonNodeId.kFBSkeletonRightWristIndex,
74  FBSkeletonNodeId.kFBSkeletonRightPinkyBIndex : FBSkeletonNodeId.kFBSkeletonRightPinkyAIndex,
75  FBSkeletonNodeId.kFBSkeletonRightPinkyCIndex : FBSkeletonNodeId.kFBSkeletonRightPinkyBIndex
76  };
77 
78 lSkeletonNodeCharacterizationMapping = {
79  FBSkeletonNodeId.kFBSkeletonReferenceIndex : "ReferenceLink",
80  FBSkeletonNodeId.kFBSkeletonHipsIndex : "HipsLink",
81  FBSkeletonNodeId.kFBSkeletonLeftHipIndex : "LeftUpLegLink",
82  FBSkeletonNodeId.kFBSkeletonLeftKneeIndex : "LeftLegLink",
83  FBSkeletonNodeId.kFBSkeletonLeftAnkleIndex : "LeftFootLink",
84  FBSkeletonNodeId.kFBSkeletonLeftFootIndex : "LeftToeBaseLink",
85  FBSkeletonNodeId.kFBSkeletonRightHipIndex : "RightUpLegLink",
86  FBSkeletonNodeId.kFBSkeletonRightKneeIndex : "RightLegLink",
87  FBSkeletonNodeId.kFBSkeletonRightAnkleIndex : "RightFootLink",
88  FBSkeletonNodeId.kFBSkeletonRightFootIndex : "RightToeBaseLink",
89  FBSkeletonNodeId.kFBSkeletonWaistIndex : "SpineLink",
90  FBSkeletonNodeId.kFBSkeletonChestIndex : "Spine1Link",
91  FBSkeletonNodeId.kFBSkeletonLeftCollarIndex : "LeftShoulderLink",
92  FBSkeletonNodeId.kFBSkeletonLeftShoulderIndex : "LeftArmLink",
93  FBSkeletonNodeId.kFBSkeletonLeftElbowIndex : "LeftForeArmLink",
94  FBSkeletonNodeId.kFBSkeletonLeftWristIndex : "LeftHandLink",
95  FBSkeletonNodeId.kFBSkeletonRightCollarIndex : "RightShoulderLink",
96  FBSkeletonNodeId.kFBSkeletonRightShoulderIndex : "RightArmLink",
97  FBSkeletonNodeId.kFBSkeletonRightElbowIndex : "RightForeArmLink",
98  FBSkeletonNodeId.kFBSkeletonRightWristIndex : "RightHandLink",
99  FBSkeletonNodeId.kFBSkeletonNeckIndex : "NeckLink",
100  FBSkeletonNodeId.kFBSkeletonHeadIndex : "HeadLink",
101  FBSkeletonNodeId.kFBSkeletonLeftThumbAIndex : "LeftHandThumb1Link",
102  FBSkeletonNodeId.kFBSkeletonLeftThumbBIndex : "LeftHandThumb2Link",
103  FBSkeletonNodeId.kFBSkeletonLeftThumbCIndex : "LeftHandThumb3Link",
104  FBSkeletonNodeId.kFBSkeletonLeftIndexAIndex : "LeftHandIndex1Link",
105  FBSkeletonNodeId.kFBSkeletonLeftIndexBIndex : "LeftHandIndex2Link",
106  FBSkeletonNodeId.kFBSkeletonLeftIndexCIndex : "LeftHandIndex3Link",
107  FBSkeletonNodeId.kFBSkeletonLeftMiddleAIndex : "LeftHandMiddle1Link",
108  FBSkeletonNodeId.kFBSkeletonLeftMiddleBIndex : "LeftHandMiddle2Link",
109  FBSkeletonNodeId.kFBSkeletonLeftMiddleCIndex : "LeftHandMiddle3Link",
110  FBSkeletonNodeId.kFBSkeletonLeftRingAIndex : "LeftHandRing1Link",
111  FBSkeletonNodeId.kFBSkeletonLeftRingBIndex : "LeftHandRing2Link",
112  FBSkeletonNodeId.kFBSkeletonLeftRingCIndex : "LeftHandRing3Link",
113  FBSkeletonNodeId.kFBSkeletonLeftPinkyAIndex : "LeftHandPinky1Link",
114  FBSkeletonNodeId.kFBSkeletonLeftPinkyBIndex : "LeftHandPinky2Link",
115  FBSkeletonNodeId.kFBSkeletonLeftPinkyCIndex : "LeftHandPinky3Link",
116  FBSkeletonNodeId.kFBSkeletonRightThumbAIndex : "RightHandThumb1Link",
117  FBSkeletonNodeId.kFBSkeletonRightThumbBIndex : "RightHandThumb2Link",
118  FBSkeletonNodeId.kFBSkeletonRightThumbCIndex : "RightHandThumb3Link",
119  FBSkeletonNodeId.kFBSkeletonRightIndexAIndex : "RightHandIndex1Link",
120  FBSkeletonNodeId.kFBSkeletonRightIndexBIndex : "RightHandIndex2Link",
121  FBSkeletonNodeId.kFBSkeletonRightIndexCIndex : "RightHandIndex3Link",
122  FBSkeletonNodeId.kFBSkeletonRightMiddleAIndex : "RightHandMiddle1Link",
123  FBSkeletonNodeId.kFBSkeletonRightMiddleBIndex : "RightHandMiddle2Link",
124  FBSkeletonNodeId.kFBSkeletonRightMiddleCIndex : "RightHandMiddle3Link",
125  FBSkeletonNodeId.kFBSkeletonRightRingAIndex : "RightHandRing1Link",
126  FBSkeletonNodeId.kFBSkeletonRightRingBIndex : "RightHandRing2Link",
127  FBSkeletonNodeId.kFBSkeletonRightRingCIndex : "RightHandRing3Link",
128  FBSkeletonNodeId.kFBSkeletonRightPinkyAIndex : "RightHandPinky1Link",
129  FBSkeletonNodeId.kFBSkeletonRightPinkyBIndex : "RightHandPinky2Link",
130  FBSkeletonNodeId.kFBSkeletonRightPinkyCIndex : "RightHandPinky3Link",
131  };
132 
133 def dic_find_key(dic, val):
134  return [k for k, v in dic.iteritems() if v == val][0]
135 
136 def replace_end(pString, pOldEnd, pNewEnd, pTestForExistence=False):
137  if pTestForExistence == False or pString.endswith(pOldEnd):
138  return pString[:(len(pString) - len(pOldEnd))] + pNewEnd
139  else:
140  return pString
141 
142 def GetFBBodyNodeIdFromFBSkeletonId(pIndex):
143  lName = dic_find_key(FBSkeletonNodeId.names, pIndex).replace('kFBSkeleton','kFB')
144  lName = lName[:(len(lName) - len('Index'))] + 'NodeId'
145  lBodyId = FBBodyNodeId.names[lName]
146  return lBodyId
147 
148 def GetFBEffectorIdFromFBSkeletonId(pIndex):
149  lName = dic_find_key(FBSkeletonNodeId.names, pIndex).replace('kFBSkeleton','kFB')
150  lName = lName[:(len(lName) - len('Index'))] + 'EffectorId'
151 
152  lEffectorId = None
153 
154  for k, v in FBEffectorId.names.iteritems():
155  if k == lName:
156  lEffectorId = v
157  break
158 
159  #special case for waist and chest
160  if lEffectorId == None:
161  if FBSkeletonNodeId.values[pIndex] == FBSkeletonNodeId.kFBSkeletonWaistIndex:
162  lEffectorId = FBEffectorId.kFBChestOriginEffectorId
163  elif FBSkeletonNodeId.values[pIndex] == FBSkeletonNodeId.kFBSkeletonChestIndex:
164  lEffectorId = FBEffectorId.kFBChestEndEffectorId
165 
166  return lEffectorId
167 
168 def GetActorNodeNameFromFBSkeletonId(pIndex, pPrefix):
169  lName = dic_find_key(FBSkeletonNodeId.names, pIndex).replace('kFBSkeleton',pPrefix)
170  lName = replace_end(lName, 'AIndex', '1', True)
171  lName = replace_end(lName, 'BIndex', '2', True)
172  lName = replace_end(lName, 'CIndex', '3', True)
173  lName = replace_end(lName, 'Index', '', True)
174  return lName
175 
176 def GetFBSkeletonNodeIdName(pIndex, pPrefix):
177  lName = dic_find_key(FBSkeletonNodeId.names, pIndex).replace('kFBSkeleton',pPrefix)
178  return lName[:(len(lName) - len('Index'))]
179 
180 def GetFBSkeletonNodeIdParentId(pIndex):
181  return lSkeletonNodeParentIds[FBSkeletonNodeId.values[pIndex]]
182 
183 def IsValidSkeletonNodeId(pIndex):
184  return pIndex >= 0 and pIndex < FBSkeletonNodeId.kFBSkeletonLastIndex
185 
186 def GetOrCreateSkeletonNode(pIndex,pPrefix,pCreateIfNotExisting=True):
187  if IsValidSkeletonNodeId(pIndex) == False:
188  return None
189 
190  lName = GetFBSkeletonNodeIdName(pIndex,pPrefix)
191 
192  lSkeletonNode = FBFindObjectByFullName('Model::'+lName)
193  if lSkeletonNode == None and pCreateIfNotExisting:
194  if FBSkeletonNodeId.values[pIndex] != FBSkeletonNodeId.kFBSkeletonReferenceIndex:
195  lSkeletonNode = FBModelSkeleton(lName)
196  else:
197  lSkeletonNode = FBModelNull(lName)
198  lSkeletonNode.Show = True
199 
200  return lSkeletonNode
201 
202 def GetActorBonesModel(pIndex):
203  if IsValidSkeletonNodeId(pIndex) == False:
204  return None
205 
206  lName = GetActorNodeNameFromFBSkeletonId(pIndex,'ActorBodyBone:')
207  lActorBoneModel = FBFindObjectByFullName('Model::'+lName)
208 
209  return lActorBoneModel
210 
211 '''
212 # end of helper functions
213 '''
214 
215 # Set new external solver for character
216 def SetSolver(pCharacter, pSolverName):
217  # remove solver
218  for lComp in pCharacter.Components:
219  if lComp.Name.startswith('HIK'):
220  lComp.FBDelete()
221  break
222  # find index of solver
224  for lSoverIndex in range(len(lSolverNames)):
225  if lSolverNames[lSoverIndex] == pSolverName:
226  pCharacter.SetExternalSolverWithIndex(lSoverIndex)
227 
228 # Map skeleton model to character characterization slot
229 def MapSkeletonBone(pCharacter, pIndex, pPrefix):
230  lModel = GetOrCreateSkeletonNode(pIndex,pPrefix)
231 
232  if lModel != None and pCharacter != None:
233  lMappingPropName = lSkeletonNodeCharacterizationMapping[FBSkeletonNodeId.values[pIndex]]
234  lMappingProp = pCharacter.PropertyList.Find(lMappingPropName,False)
235  if lMappingProp != None:
236  lMappingProp.ConnectSrc(lModel)
237  else:
238  print 'Could not characterize: ' + lModel.Name + '; MappingName: ' + lMappingPropName
239 
240 # Get default extraction for character marker set (no magic in here, simply hard coded)
241 def GetDefaultExtraction(pNodeId, pMarkerCount):
242  if pMarkerCount >= 3:
243  if pNodeId == FBBodyNodeId.kFBHipsNodeId or pNodeId == FBBodyNodeId.kFBChestNodeId or pNodeId == FBBodyNodeId.kFBHeadNodeId:
244  return 0
245  if pNodeId == FBBodyNodeId.kFBLeftWristNodeId or pNodeId == FBBodyNodeId.kFBRightWristNodeId:
246  return 0
247  if pNodeId == FBBodyNodeId.kFBLeftAnkleNodeId or pNodeId == FBBodyNodeId.kFBRightAnkleNodeId:
248  return 0
249  return 1
250 
251 # Copy marker assignment in from source to destination if destination is empty
252 def CopyAssignmentIfEmpty(pCharacterMarkerSet, pDstBodyNodeId, pSrdBodyNodeId, pExtractionToSet=1):
253  lDstMarkersProp = pCharacterMarkerSet.GetMarkersProperty(pDstBodyNodeId)
254 
255  if lDstMarkersProp != None and lDstMarkersProp.GetSrcCount() == 0:
256  lSrcMarkersProp = pCharacterMarkerSet.GetMarkersProperty(pSrdBodyNodeId)
257 
258  if lSrcMarkersProp != None:
259  lDstMarkersProp.BeginChange()
260 
261  for lSrcIndex in range(lSrcMarkersProp.GetSrcCount()):
262  lDstMarkersProp.ConnectSrc(lSrcMarkersProp.GetSrc(lSrcIndex))
263 
264  lDstExtractionProp = pCharacterMarkerSet.GetExtractionProperty(pDstBodyNodeId)
265  if lDstExtractionProp != None:
266  lDstExtractionProp.Data = pExtractionToSet
267 
268  lDstMarkersProp.EndChange()
269 
270  print "Override done for: " + str(pDstBodyNodeId)
271 
272 # Create skeleton from actor current state (with stance rotations)
273 def CreateSkeletonForActor(pActor,pPrefix):
274  lState = pActor.GetCurrentSkeletonState(True)
275  lGX = FBMatrix()
276 
277  for enum in FBSkeletonNodeId.values:
278  if IsValidSkeletonNodeId(enum):
279  lState.GetNodeMatrix(FBSkeletonNodeId.values[enum],lGX)
280 
281  lSkeletonNode = GetOrCreateSkeletonNode(enum,pPrefix)
282 
283  lParentId = GetFBSkeletonNodeIdParentId(enum)
284  lParentSkeletonNode = GetOrCreateSkeletonNode(lParentId,pPrefix)
285 
286  lSkeletonNode.SetMatrix(lGX)
287 
288  if lParentSkeletonNode != None:
289  lSkeletonNode.Parent = lParentSkeletonNode
290 
291 # Apply actpr state on characterized character
292 def ApplyStateFor(pCharacter,pState):
293  lGX = FBMatrix()
294 
295  for enum in FBSkeletonNodeId.values:
296  if IsValidSkeletonNodeId(enum) and enum != FBSkeletonNodeId.kFBSkeletonReferenceIndex:
297  pState.GetNodeMatrix(FBSkeletonNodeId.values[enum],lGX)
298  lBodyNodeId = GetFBBodyNodeIdFromFBSkeletonId(enum)
299 
300  lSkeletonNode = pCharacter.GetModel(lBodyNodeId)
301  lSkeletonNode.SetMatrix(lGX)
302 
303  FBSystem().Scene.Evaluate()
304 
305 # Create characterized character from actor
306 def CharacterizeActorSkeleton(pPrefix):
307  lCharacter = FBCharacter(pPrefix+'Character')
308  # Character marker set is supported on default MoBu solver or HIK 2014 and above.
309  SetSolver(lCharacter,'HIK 2014 Solver')
310 
311  for enum in FBSkeletonNodeId.values:
312  if IsValidSkeletonNodeId(enum):
313  MapSkeletonBone(lCharacter, enum, pPrefix)
314 
315  lCharacter.SetCharacterizeOn(True)
316  FBSystem().Scene.Evaluate()
317 
318  return lCharacter
319 
320 # Create Character Marker Set input for pCharDst and copy marker assignment from pActorSrc
321 def CopyMarkerMappingFromActorToCharacter(pCharDst, pActorSrc):
322  # Get marker set from actor to get access to mapping
323  lSrc = pActorSrc.MarkerSet
324  # Create Marker Set
325  pCharDst.CreateCharacterMarkerSet(False)
326  # Get pointer to newly created marker set (force get, since it's not active)
327  lDst = pCharDst.GetCharacterMarkerSet(True)
328 
329  # Stop refreshes
331 
332  # For every possible skeleton node
333  for enum in FBSkeletonNodeId.values:
334  # If it's valid, copy marker assignment
335  if IsValidSkeletonNodeId(enum) and enum != FBSkeletonNodeId.kFBSkeletonReferenceIndex:
336  lSkID = FBSkeletonNodeId.values[enum]
337  lAssignMarkers = []
338 
339  for lMarkerIndex in range(lSrc.GetMarkerCount(lSkID)):
340  if lSrc.GetMarkerUsed(lSkID, lMarkerIndex) == False:
341  continue
342 
343  if lSrc.GetMarkerOriented(lSkID, lMarkerIndex) == False:
344  lAssignMarkers.append(lSrc.GetMarkerModel(lSkID, lMarkerIndex))
345  else:
346  print "Oriented marker set is unsupported in here"
347 
348  if len(lAssignMarkers) > 0:
349  lBodyNodeId = GetFBBodyNodeIdFromFBSkeletonId(enum)
350  lMarkersProp = lDst.GetMarkersProperty(lBodyNodeId)
351 
352  if lMarkersProp != None:
353  # start transaction to perform less refresh
354  lMarkersProp.BeginChange()
355 
356  for lMarker in lAssignMarkers:
357  lMarkersProp.ConnectSrc(lMarker)
358 
359  # adjust extraction
360  lExtractionProp = lDst.GetExtractionProperty(lBodyNodeId)
361  if lExtractionProp != None:
362  lExtractionProp.Data = GetDefaultExtraction(lBodyNodeId, len(lAssignMarkers))
363 
364  lMarkersProp.EndChange()
365 
366  # Character Marker Set is not a "black box" like character, for better solving it require knees and elbows to be assigned
367  CopyAssignmentIfEmpty(lDst, FBBodyNodeId.kFBLeftElbowNodeId, FBBodyNodeId.kFBLeftWristNodeId)
368  CopyAssignmentIfEmpty(lDst, FBBodyNodeId.kFBRightElbowNodeId, FBBodyNodeId.kFBRightWristNodeId)
369  CopyAssignmentIfEmpty(lDst, FBBodyNodeId.kFBLeftKneeNodeId, FBBodyNodeId.kFBLeftAnkleNodeId)
370  CopyAssignmentIfEmpty(lDst, FBBodyNodeId.kFBRightKneeNodeId, FBBodyNodeId.kFBRightAnkleNodeId)
371 
372  # Release refresh
374 
375 # All in one, convert given actor to character, prefix is used to easy localize recreated skeleton models and character
376 def ConvertActorToCharacter(pActor, pPrefix):
377  # create skeleton from actor
378  CreateSkeletonForActor(pActor,pPrefix)
379 
380  # setup characterization and lock character
381  lChar = CharacterizeActorSkeleton(pPrefix)
382 
383  # prepare for snap
384  ApplyStateFor(lChar, pActor.GetCurrentSkeletonState(False))
385 
386  # snap markers on character marker set
387  CopyMarkerMappingFromActorToCharacter(lChar, pActor)
388 
389  # set character marker set input
390  lChar.InputType = FBCharacterInputType.kFBCharacterInputMoCap
391 
392  # Activate Input
393  lChar.Active = True
394 
395 # If there is actor in the scene, convert first one.
396 if len(FBSystem().Scene.Actors) > 0: ConvertActorToCharacter(FBSystem().Scene.Actors[0],'ActorSkeleton:')