從Blender裡萃取模組資料(8)
前言
續前篇從Blender裡萃取模組資料(7),這次說明萃取Skeleton的動畫,在此做個紀錄。內容
如果使用前篇的範例來萃取Skeleton的動畫,應該會發現竟然完全沒問題,可以正常執行,但若仔細一看"Data path"的欄位,就會發現它有何不同了,就拿"location"來說,在Skeleton的動畫可能會是"pose.bones["spine"].location",其中的"spine"為該Bone的名稱。這裡有個陷阱!如果你直覺地用字串的split()來parse這個"Data path"的欄位的話會有問題,問題會發生在Bone的名稱是可以包含".",舉例來說如果Bone的名稱是"spine.001"的話,"Data path"就會變成"pose.bones["spine.001"].location",接著split()後就變成"[pose, bones["spine, 001, location]",明顯的,Bone的名稱會被切到,還必須注意Blender的名稱可以很自由,名稱裡可以出現單引號或雙引號,所以需要特製的Parse。接著用前篇的範例為基礎,製作出以下範例
import bpy def ShowActionInfo(act): print('animation name',act.name) for curve in act.fcurves: print('Data path:',curve.data_path,' ',end='') print('') if curve.data_path == 'location': print("Data from transform.location") elif curve.data_path == 'rotation_euler': print("Data from transform.rotation_euler") elif curve.data_path == 'rotation_euler': print("Data from transform.rotation_quaternion") elif curve.data_path == 'scale': print("Data from transform.scale") elif curve.data_path[:12] == 'pose.bones["': namelastIndex = curve.data_path.rfind('"') if namelastIndex >= 0: boneName = curve.data_path[12:namelastIndex] propertyNameIndex = curve.data_path.rfind('.') if propertyNameIndex >= 0: propertyName = curve.data_path[ (propertyNameIndex+1):] if propertyName == 'location': print('Bone:',boneName,' Property:transform.location') elif propertyName == 'rotation_euler': print('Bone:',boneName,' Property:transform.rotation_euler') elif propertyName == 'rotation_quaternion': print('Bone:',boneName,' Property:transform.rotation_quaternion') elif propertyName == 'scale': print('Bone:',boneName,' Property:transform.scale') else: print('Unknown property:',propertyName) else: print('Parse skeleton property error!') else: print('Parse skeleton bone name error!') else: print("Unknown data path!") print('Array index:',curve.array_index,' ',end='') print('') for keyFrame in curve.keyframe_points: print('Key time:',keyFrame.co[0],' ',end='') print('Key value:',keyFrame.co[1],' ',end='') print('') # def ShowAnimationInfo(obj): if obj.animation_data == None: print("No animation data in object!") return #Check actived action... actionCon = 0 if obj.animation_data.action != None: ShowActionInfo(obj.animation_data.action) actionCon+=1 #Check action in NLA tracks... for track in obj.animation_data.nla_tracks: for strip in track.strips: ShowActionInfo(strip.action) actionCon +=1 print("Animation amount:",actionCon ) # tagObj = bpy.data.objects['metarig'] ShowAnimationInfo(tagObj )
可以看到ShowActionInfo()裡多了非常多的if判斷,目前沒找到比較簡易的寫法,目前的作法以直觀與好懂為原則, 所以程式碼相當長。Bone的名稱如之前所說由於編輯器可以相當自由命名,所以用rfind()來找,property的部分也 是使用rfind()來找也請注意。
沒有留言:
張貼留言