從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()來找也請注意。
沒有留言:
張貼留言